-
Notifications
You must be signed in to change notification settings - Fork 731
Description
Description
Version 6.0.0 introduced an undocumented breaking change from version 5.10.3. In older versions, actual.Should().Be(expected) would pass when actual and expected were of the same type and that type implemented IComparable<T> and the CompareTo implementation returned 0. Tests that relied on this now fail in versions 6.0.0 and 6.1.0.
Interestingly, NUnit's Assert.AreEqual fails to pass in this situation as well but it does pass if the class implements IEquatable<T> and the Equals implementation returns true.
Neither the older or newer versions of FluentAssertions will pass Should().Be() for the IEquatable<T> scenario.
Complete minimal example reproducing the issue
using FluentAssertions;
using NUnit.Framework;
namespace FluentAssertionBug
{
public class ClassToBeComparedWithIComparable : IComparable<ClassToBeComparedWithIComparable>
{
public string Id { get; set; }
public int Value { get; set; }
public int CompareTo(ClassToBeComparedWithIComparable other)
{
var c = string.Compare(Id, other.Id, StringComparison.Ordinal);
return c != 0 ? c : Value.CompareTo(other.Value);
}
}
public class ClassToBeComparedWithIEquatable : IEquatable<ClassToBeComparedWithIEquatable>
{
public string Id { get; set; }
public int Value { get; set; }
public bool Equals(ClassToBeComparedWithIEquatable other)
{
if (other == null)
return false;
return Id.Equals(other.Id) && Value.Equals(other.Value);
}
}
[TestFixture]
public class Tests
{
[Test]
public void GivenTwoIComparablesThatHaveIdenticalValues_ShouldBe_ShouldPass_WillFailInNewerVersions()
{
var value1 = new ClassToBeComparedWithIComparable { Id = "One", Value = 1 };
var value2 = new ClassToBeComparedWithIComparable { Id = "One", Value = 1 };
value1.Should().Be(value2);
}
[Test]
public void GivenTwoIEquatablesThatHaveIdenticalValues_Equals_ShouldPass()
{
var value1 = new ClassToBeComparedWithIEquatable { Id = "One", Value = 1 };
var value2 = new ClassToBeComparedWithIEquatable { Id = "One", Value = 1 };
if (value1.Equals(value2))
Assert.Pass();
Assert.Fail();
}
[Test]
public void GivenTwoIEquatablesThatHaveIdenticalValues_AssertAreEqual_ShouldPass()
{
var value1 = new ClassToBeComparedWithIEquatable { Id = "One", Value = 1 };
var value2 = new ClassToBeComparedWithIEquatable { Id = "One", Value = 1 };
Assert.AreEqual(value2, value1);
}
}
}Expected behavior:
I expect the breaking change for the IComparable<T> scenario to be documented.
I expect Should().Be() to honor the IEquatable<T> implementation when determining if 2 objects are equal.
Actual behavior:
Neither the 6.0.0 nor the 6.1.0 documentation mention that Should().Be() no longer honors the IComparable<T> implementation when determining equality.
Should().Be() does not honor the IEquatable<T> implementation when determining equality.
Versions
- I upgraded from FluentAssertion 5.10.3 to 6.1.0. (I also tried using 6.0.0 to determine when the break first occurred.)
- I am using .Net Core 3.1
- I am using NUnit 3.13.2 as my testing suite.