Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assert that value is equal to any of a collection of expected values

Does NUnit provide a constraint to find whether the actual value is the element of a given enumerable or array, in other words, that it is equal to any of multiple expected values? Something like:

Assert.That(actual, Is.EqualToAnyOf(new[] { 1, 2, 3 }))

That is, to point out, the actual is a single value. I expect the value to be either 1, 2, or 3. The assertion

Assert.That(actual, Contains.Element(expected))

checks logically the same, but it is the opposite intention: Here we have a collection of actual values and expect one value to be in it.

Furthermore, I found these but they all don't fit:

Assert.That(actual, Is.EqualTo(expected)) // only allows one value
Assert.That(actual, Is.InRange(start, end)) // only works for consecutive numbers
Assert.That(actual, Is.SubsetOf(expected)) // only works if actual is an enumerable
Assert.That(expected.Contains(actual)) // meaningless "expected: true but was: false" message
like image 932
chiccodoro Avatar asked Aug 27 '14 08:08

chiccodoro


People also ask

What is assert equal?

The assert. equal() method tests if two values are equal, using the == operator. If the two values are not equal, an assertion failure is being caused, and the program is terminated. To compare the values using the === operator, use the assert.

How do you assert two values in Java?

Method 1: using == operator Double equals operator is used to compare two or more than two objects, If they are referring to the same object then return true, otherwise return false. String is immutable in java. When two or more objects are created without new keyword, then both object refer same value.

What is assert that in Nunit?

Asserts that a condition is true. If the condition is false the method throws an AssertionException. That(Object, IResolveConstraint) Apply a constraint to an actual value, succeeding if the constraint is satisfied and throwing an assertion exception on failure.


4 Answers

CollectionAssert should be what you need if I am not overlooking something. It is as simple as:

CollectionAssert.Contains(IEnumerable expected, object actual);

However, there seems to be several ways to achieve your goal, such as:

[Test]
public void CollectionContains()
{
    var expected = new List<int> { 0, 1, 2, 3, 5 };
    var actual = 5;

    CollectionAssert.Contains(expected, actual);
    Assert.That(expected, Contains.Item(actual));
}

Above assertions should basically assert the same and could be used interchangeably.

Edit: Question was modified, stating that Assert.That(expected, Contains.Item(actual)); is not valid even though it logically tests the same thing.

like image 144
Michal Hosala Avatar answered Sep 21 '22 12:09

Michal Hosala


There is a way to do this built in to NUnit, using the Or constraint:

Assert.That(actual, Is.EqualTo(1).Or.EqualTo(2).Or.EqualTo(3))

If your list is more dynamic, you can build your list of Ors like this:

var expected = new[] { 1, 2, 3 };
var constraints = Is.EqualTo(expected[0]);

for(var i = 1; i < expected.Length; i++)
    constraints = constraints.Or.EqualTo(expected[i]);

Assert.That(actual, constraints);

That latter answer doesn't read as well in the fluid syntax, but does achieve the dynamic building of or constraints. You could probably wrap that in a custom constraint as patrick-quirk demonstrated in order to achieve a more readbale fluid syntax, but that's up to you.

like image 44
cidthecoatrack Avatar answered Sep 22 '22 12:09

cidthecoatrack


I know this is an old question, bu I have a maybe better (and native) suggestion. With NUnit 3.x (I'm on 3.10.1) you can use Is.AnyOf:

 Assert.That(
actualValue, 
Is.AnyOf(expectedValue1, expectedValue2, expectedValue3),
"My error message");
like image 27
NinjaCross Avatar answered Sep 19 '22 12:09

NinjaCross


The only way I could see to accomplish this is by creating your own constraint. It's pretty straightforward to do though.

The constraint class itself:

public class OneOfValuesConstraint : EqualConstraint
{
    readonly ICollection expected;
    NUnitEqualityComparer comparer = new NUnitEqualityComparer();

    public OneOfValuesConstraint(ICollection expected)
        : base(expected)
    {
        this.expected = expected;
    }

    public override bool Matches(object actual)
    {
        // set the base class value so it appears in the error message
        this.actual = actual;
        Tolerance tolerance = Tolerance.Empty;

        // Loop through the expected values and return true on first match
        foreach (object value in expected)
            if (comparer.AreEqual(value, actual, ref tolerance))
                return true;

        // No matches, return false
        return false;
    }

    // Overridden for a cleaner error message (contributed by @chiccodoro)
    public override void WriteMessageTo(MessageWriter writer)
    {
        writer.DisplayDifferences(this);
    }

    public override void WriteDescriptionTo(MessageWriter writer)
    {
        writer.Write("either of ");
        writer.WriteExpectedValue(this.expected);
    }
}

And to make it fluent, create a static method to wrap it (contributed by @chicodorro):

public static class IsEqual
{
    public static OneOfValuesConstraint ToAny(ICollection expected)
    {
        return new OneOfValuesConstraint(expected);
    }
}    

Then to use it:

int[] expectedValues = new[] { 0, 1, 2 };
Assert.That(6, IsEqual.ToAny(expectedValues));

Fails with the message:

Expected: either of < 0, 1, 2 >

But was: 6

like image 34
Patrick Quirk Avatar answered Sep 19 '22 12:09

Patrick Quirk