Search code examples
c#nunitequality

Provide equality for NUnits results


We have the Result-argument for all kinds of parameterized tests on NUnit. This works well for simple types where equality is built into .NET. However I wonder if there´s a way to verify a test-method returns a complex object:

[TestCase("MyValue", Result = new MyType(...) /* doesn't work as we can only use compile-time constants for attributes */]
public MyType Check(string value)
{
    var target = ...
    return target.DoSomething(value);
}

Assuming target.DoSomething returns an instance of MyType the test should ensure that the returned instance is equal to what I provided within my TestCase. As MyType does neither implement IEquatable nor override Equals equality is determined using ReferenceEquals which of course is wrong. Moreover as mentioned in my comment we can't create an instance of MyType within the attribute as it's no compile-time constant.

So how can we provide a complex instance to our test and check if the outcome is equal to that one?


Solution

  • We can use the TestCaseSource-attribute for this which allows to determine a member that provides more sophisticated use for testcases. Thus we can also return complex instances of any type. However as allready mentioned we can´t rely on the Result-tag of our TestCase as it implicitely compare the provided instance with te returned one using the default comparerer which uses ReferencEEquals.

    So we don´t provide the expected outcome as Result but as simple argument to the test and provide our own logic for what is condidered equal:

    [TestCaseSource("TestcaseMethod")] 
    public MyType Check(string value, MyType expected)
    {
        var target = ...
        var actual = target.DoSomething(value);
        bool retVal = // check the properties of actual towards those of expected
        Assert.IsTrue(retVal);
    }
    public IEnumerable<object> TestcaseMethod()
    {
        yield return new object[] { "MyValue", new MyType(/* expected outcome */);
        yield return new object[] { "AnotherValue", new MyType(/* expected outcome */);
    }
    

    where

    public class MyType
    {
        // here come the actual values to be compared
    }
    

    EDIT: A more straightforward way to check for equality in an Assert-statement is to use an EqualConstraint:

    Assert.That(expected, Is.EqualTo(actual).Using(new MyComparer());
    

    which will use a custom comparer.