Why is my implementation of Equals () not called AreEqual ()

I saw a lot of instructions ( Why Assert.AreEqual (T obj1, Tobj2) fails with identical objects , Unit Test Error Assert.AreEqual , Assert.AreEqual fails with the same type ) to implement Equals / IEqualityComparer for my classes, if I I want to test equality based on field values, not links.

In an attempt to do this, I could not get it to work and narrow down the problem to the next.

My class Subject must be tested. In SubjectTestEqual, I would expect both instances to be equal, but the result "Assert.AreEqual failed. Also, if I debug the code, I don't see any Equals or GetHashCode calls.

Based on the hoax, the Default property checks to see if Type T implements the System.IEquatable interface, and if so, returns EqualityComparer that uses this implementation. Otherwise, it returns EqualityComparer that uses the overrides of Object.Equals and Object.GetHashCode provided by T. " in the EqualityComparer.Default Property documentation , I also tried with IEquatable (uncomment code to see the effect) to no avail.

 public class Subject : IEqualityComparer<Subject>//, IEquatable<Subject> { public int Id { get; set; } public Subject(int name) { Id = name; } public bool Equals(Subject x, Subject y) { return (x.Id == y.Id); } public int GetHashCode(Subject obj) { return Id; } //public bool Equals(Subject other) //{ return Equals(this, other); } } [TestClass] public class SubjectTest { [TestMethod] public void SubjectTestEqual() { Assert.AreEqual<Subject>(new Subject(1), new Subject(1)); } [TestMethod] public void SubjectTestSame() { Subject test = new Subject(1); Assert.AreEqual<Subject>(test, test); } } 

Can anyone shed some light on this?

+4
source share
4 answers

You need to override the base methods to call them:

 public override bool Equals(object obj) { ... } public override int GetHashCode() { ... } 

But you must use the same signatures as the basic Equals and GetHashcode .

+5
source

Thank you for your answers, they helped me in the future, but none of them helped me completely.

If I override the Equals and GetHashCode methods of the object as follows:

 public override bool Equals(object obj) { return true; } public override int GetHashCode() { return 0; } 

methods are called and my tests will succeed. However, of course, I do not want to implement these methods for the parameters of an object of type. Why does my class offer to compare instances only with any instance of an object?

So, I modified this method as static: public **static** bool Equals(Subject x, Subject y) and introduced a new test method (all tests in one method for short):

  [TestMethod] public void SubjectTestWithSubjectEquals() { Assert.IsTrue(Subject.Equals(new Subject(1), new Subject(1))); Assert.IsTrue(new Subject(1).Equals(new Subject(1))); Assert.IsFalse(Subject.Equals(new Subject(1), new Subject(2))); Assert.IsFalse(new Subject(1).Equals(new Subject(2))); } 

These tests will succeed. However, I'm not sure if this is a good way. Firstly, for success Assert.IsTrue((new Subject(1)) == (new Subject(1))); I needed to implement:

 public static bool operator ==(Subject x, Subject y) { return Equals(x, y); } 

and it also causes:

 public static bool operator !=(Subject x, Subject y) { return !Equals(x, y); } 

In addition, taking another step, wanting to be able to compare lists of type Subject, I tried this test:

 [TestMethod] public void SubjectTestWithCollections() { var list1 = new List<Subject>() { new Subject(1), new Subject(2) }; var list2 = new List<Subject>() { new Subject(1), new Subject(2) }; CollectionAssert.AreEqual(list1, list2); } 

this will not work, since, apparently, each element will be compared using Assert.AreEqual, not Subject.Equals. I saw problems with CollectionAssert.AreEquivalent , which makes me wonder if this is mainly due to the way Microsoft.VisualStudio.TestTools.UnitTesting is implemented, or that I shouldn’t try to fuss with peers in general.

+1
source

Your TestClass violates the Object.Equals contract. Assert.AreEqual relies on this contract fairly reasonably.

Status of documents (in the list of requirements):

x.Equals (null reference (Nothing in Visual Basic)) returns false.

0
source

Assert.AreEqual will use the Equals method of the first parameter passed. Now he knows your implementation of IEqualityComparer , so it will not be used.

Usually, when a class must compare objects for equality, it will have an optional parameter IEqualityComparer , which the class can use instead of the Equals method of the object itself, however Assert.AreEqual accepts no such parameter. This means that to use Assert.AreEqual you need to override the Equals method inherited from object , which:

public override bool Equals (obj object) {}

It does not really matter for the type to implement IEqualityComparer its own type. The idea of IEqualityComparer is that it allows you to compare a different type for equality, rather than "on your own."

0
source

All Articles