tpierrain / NFluent

Smooth your .NET TDD experience with NFluent! NFluent is an ergonomic assertion library which aims to fluent your .NET TDD experience (based on simple Check.That() assertion statements). NFluent aims your tests to be fluent to write (with a super-duper-happy 'dot' auto-completion experience), fluent to read (i.e. as close as possible to plain English expression), but also fluent to troubleshoot, in a less-error-prone way comparing to the classical .NET test frameworks. NFluent is also directly inspired by the awesome Java FEST Fluent assertion/reflection library (http://fest.easytesting.org/)
Apache License 2.0
310 stars 53 forks source link

Providing an `IEqualityComparer` for comparison #330

Closed MiniKeb closed 1 year ago

MiniKeb commented 4 years ago

If I write a method that return an object with a type from a library, I can't add or modify the Equals() method's of this type. This imply that I won't be able to compare by value rather than by reference and my assertion will failed.

Expected Behavior

It would be nice if I could define my own IEqualityComparer :

public class CustomComparer : IEqualityComparer<Item>
{
    public bool Equals(Item x, Item y)
    {
        if (ReferenceEquals(null, x) || ReferenceEquals(null, y)) return false;
        if (ReferenceEquals(x, y)) return true;
        return x.Name == y.Name && x.Number == y.Number;
    }

    public int GetHashCode(Item obj)
    {
        return HashCode.Combine(obj.Name, obj.Number);
    }
}

And use it in my test :

var items = sut.MyMethod(withParameter).ToArray();

var expected = new[]
{
    new Item
    {
        Name = "ItemA",
        Number = 111
    },
    new Item
    {
        Name = "ItemB",
        Number = 222
    }
};

Check.That(items).ContainsExactly(expected, new CustomComparer());
//OR
Check.RegisterEqualityComparer<Item>(new CustomComparer()) 
Check.That(items).ContainsExactly(expected);
dupdob commented 4 years ago

Thanks for your feedback. I have a working prototype that supports the register approach. As such, once a comparer is registered it is used for every relevant check. Therefore you can also unregister it. This looks like this:

Check.RegisterComparer<Item>(new CustomComparer());
Check.That(items).ContainsExactly(expected);

The recommended pattern is

try
{
  var previous = Check.RegisterComparer<Item>(new CustomComparer());
  Check.That(items).ContainsExactly(expected);
}
finally
{
 // restore previous comparer
  Check.RegisterComparer<Item>(previous);
}

Note that this feature requires some caching logic as searching for comparers will slow every test, so this requires extra work. But the feature will be available in the V3.0

expect a new beta in the coming days