I think the biggest reason to fix it would be for consistency. Right now, if you override the equality operation, it will use the custom comparison EXCEPT for the case where one side is null. That means that you would essentially need to document the Assert.AreEqual method to say that it uses the custom comparison for types that override Object::Equals but performs a reference comparison when 'actual' or 'expected' is null. As an API developer, this sounds like a documentation nightmare. And since most programmers aren't inclined to read the documentation anyway, once they see that it uses their custom implementation once, they will assume that it always uses the custom implementation.
I'm not thrilled with the NullObject API I'm using, but its documentation recommends using 'resultObj != null' as the null check even in cases where the NullObject might be returned. Having written 'if (resultObje != null)' all over production code, I instinctively wrote 'Assert.IsNotNull(resultObj)' in my test code. Only to have them fail unexpectedly later on when trying to perform an unsupported operation on the NullObject. I can completely back the idea that IsNull and IsNotNull should be reference comparisons to the null pointer, but with the same Equality logic underneath, it is closely coupled to the AreEqual ambiguity. Chances are that a caller isn't going to test every particular circumstance. If I have a type that overrides .Equals, I would run a quick test to see if something like AreEqual is using reference comparison or calling my custom comparison. After that first check I would assume (never a good idea, but not uncommon) that the method will always use the custom comparison. And evidence indicates that at least one otherwise talented developer has fallen into this trap already! ;) -- You received this bug notification because you are a member of NUnit Developers, which is subscribed to NUnit V2. https://bugs.launchpad.net/bugs/1157828 Title: EqualityComparer does not respect value-equality for null Status in NUnit V2 Test Framework: New Bug description: I am using a third-party library that includes Null Objects with value comparisons that return true for null. However, the NUnit equality comparer uses reference equality (via the == operator with System.Object references) to check for null and returns false if only one input is the null pointer. This means that the value-equality comparison for the custom type is never reached. The following is a quick & dirty implementation of a Null Object with a few tests that demonstrate the problem: public class MyObject { public static MyObject NullObject = new MyObject(-1); public int Value { get; set; } public MyObject(int value) { this.Value = value; } public static bool operator ==(MyObject left, MyObject right) { if (ReferenceEquals(left, NullObject) || ReferenceEquals(left, null)) return (ReferenceEquals(right, NullObject) || ReferenceEquals(right, null)); else if (ReferenceEquals(right, NullObject) || ReferenceEquals(right, null)) return false; return Equals(left, right); } public static bool operator !=(MyObject left, MyObject right) { return !(left == right); } public override bool Equals(object obj) { if (ReferenceEquals(obj, NullObject) || ReferenceEquals(obj, null)) return (ReferenceEquals(this, NullObject)); else if (ReferenceEquals(this, NullObject)) return false; MyObject myobj = obj as MyObject; if (myobj == null) return false; return this.Value == myobj.Value; } public override int GetHashCode() { return base.GetHashCode(); } } [TestFixture] public class TestNullObject { // TEST PASSES [Test] public void TestIsTrue() { Assert.IsTrue(MyObject.NullObject == null); Assert.IsTrue(null == MyObject.NullObject); } // TESTS FAIL [Test] public void TestIsNull() { Assert.IsNull(MyObject.NullObject); } [Test] public void TestAreEqual1() { Assert.AreEqual(MyObject.NullObject, null); } [Test] public void TestAreEqual2() { Assert.AreEqual(null, MyObject.NullObject); } } To manage notifications about this bug go to: https://bugs.launchpad.net/nunitv2/+bug/1157828/+subscriptions _______________________________________________ Mailing list: https://launchpad.net/~nunit-core Post to : nunit-core@lists.launchpad.net Unsubscribe : https://launchpad.net/~nunit-core More help : https://help.launchpad.net/ListHelp