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`.

Original source

Related problems