Using the MOQ framework to compare objects or: why equals are (not always) equal

In our current project we try to use the MOQ framework in order to mock away database accesss in our business logic tests. I was testing some business logic where the executed method would compare different objects and aggregations of objects with each other in order to behave one way or the other. The method builds intersections of collections using the Except extension method and stores intermediate values in lists using the Equals method. Some first tests were successful where the database wasn't mocked. Introducing mocks made me bang my head on the table because of two reasons at least:
  • Getting used to the "over-Lambda'd" syntax of MOQ and trying to guess what was really meant on the MOQ QuickStart page. The documentation is rather sparse and a lot guess work and learning-by-pain seems to be the best way to get along. At least after some time you get along with the syntax and even start to like it.
  • Lists don't behave like they behaved before. WTF! Compare will always get you a false result, even though you are comparing the same objects. Except-statements will produce wrong lists as the wrong intersections are produced
What has happened there? After a sheer endless search, overloading the HashCode etc it simply comes down to that: MOQ always returns "0" as Hashcode for their objects and implemented the "Equals" method to always return false. Have a look at this:


var someMock = new Mock<Foo>();
var obj1 = someMock.Object;
var obj2 = someMock.Object;
bool bothEqual = obj1.Equals(obj2); // returns false!!
bool referenceEquals = ReferenceEquals(obj1, obj2); // returns true!

This is also the reason why any Collection manipulation extension mehtods will fail which rely on the Equals-method of the items inside the collection. There's a simple workaround to this: mock the Equals method and implement it correctly:

someMock.Setup(role => role.Equals(It.IsAny<object>())).Returns(
                    (object obj) => ReferenceEquals(obj, roleMock.Object));
 
 
This really made me scratch my head. Lucky we found it out, though.










Kommentare

Beliebte Posts aus diesem Blog

HTML5 vs. Silverlight aka Ajax vs. Java Applets. A trip in the time machine