Moq Equals Only Works With IEquatable
c#, moq
Solution
First issue
Checked via dotPeek. `Assert.AreEqual` calls the static method `object.Equals` to compare the instances. `object.Equals` uses `operator ==` first and since the mock instance does not implement that operator, this will default to comparing references. Clearly, a and b are different instances so the comparison returns false.
Second issue
I haven't looked at the internals of Moq but I assume this happens because the interface does not declare an Equals method. Confirmed with the following (which succeeds):
public interface IBar
{
}
public class Bar : IBar
{
public override bool Equals(object obj)
{
return false;
}
}
[TestClass]
public class Class1
{
[TestMethod]
public void TestMoq()
{
var a = new Mock<Bar>();
var b = new Mock<Bar>();
a.Setup(bar => bar.Equals(b.Object)).Returns(true);
Assert.IsTrue(a.Object.Equals(b.Object));
}
}
If I remove the `Bar.Equals` override, the test will also fail. Just a guess but since Moq uses Castle internally, this issue can be explained by this Q&A.
Anyway, I think what you're doing now with `Assert.IsTrue(a.Object.Equals(b.Object));` and `IEquatable` is a sufficient workaround for this.
By the way, as JaredPar asked above, why are you comparing mocks?
Problem
I'm using the Moq framework for unit tests, and I came across this interesting problem. ``` public interface Bar : IEquatable<Bar> { } [TestClass] public class TestClass { Mock<Bar> a; Mock<Bar> b; public TestClass() { a = new Mock<Bar>(); b = new Mock<Bar>(); a.Setup(bar => bar.Equals(b.Object)).Returns(true); } [TestMethod] public void AssertEqualsTest() { Assert.AreEqual(a.Object, b.Object); //fails } [TestMethod] public void AssertIsTrueTest() { Assert.IsTrue(a.Object.Equals(b.Object)); //passes } } ``` First Issue So `Assert.AreEqual` just fails. I don't want to have to use the line from the second test every time I need to check equality even though most (if not all) of my classes inherit from IEquatable. You might think it fails because Setup is only setting the IEquality.Equals() function (which `Assert.AreEqual` probably doesn't check), but if you add the line ``` a.Setup(x => x.Equals((object)b.Object)).Returns(true); ``` to the constructor, it still fails. Second Issue If you comment out the `: IEquatable<Bar>` from the interface declaration (so that `a.Setup` overwrites `object.Equals`), both tests fail. My desired outcome is to be able to setup equals on a `Mock` object and call `Assert.AreEqual`.