Moq Equals仅适用于IEquatable [英] Moq Equals Only Works With IEquatable

查看:108
本文介绍了Moq Equals仅适用于IEquatable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Moq框架进行单元测试,并且遇到了这个有趣的问题.

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
    }
}

第一期

所以Assert.AreEqual只是失败了.我不需要每次都需要检查相等性时使用第二次测试中的代码,即使我的大多数(如果不是全部)类都从IEquatable继承.

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.

您可能会认为它会失败,因为安装程序仅设置了IEquality.Equals()函数(Assert.AreEqual可能不会检查),但是如果您添加该行

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.

第二期

如果从接口声明中注释掉: IEquatable<Bar>(以便a.Setup覆盖object.Equals),则两个测试均将失败.

If you comment out the : IEquatable<Bar> from the interface declaration (so that a.Setup overwrites object.Equals), both tests fail.

我希望得到的结果是能够在Mock对象上设置等于并调用Assert.AreEqual.

My desired outcome is to be able to setup equals on a Mock object and call Assert.AreEqual.

推荐答案

第一期

通过dotPeek检查. Assert.AreEqual调用静态方法object.Equals来比较实例. object.Equals首先使用operator ==,并且由于模拟实例未实现该运算符,因此默认情况下将比较参考.显然,a和b是不同的实例,因此比较返回false.

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.

第二个问题

我没有看过Moq的内部结构,但我认为发生这种情况是因为接口未声明Equals方法.确认以下内容(成功):

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));
    }
}

如果删除Bar.Equals替代,则测试也将失败.只是一个猜测,但是由于Moq在内部使用Castle,因此可以通过以下

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.

无论如何,我认为您现在对Assert.IsTrue(a.Object.Equals(b.Object));IEquatable所做的工作已足够解决此问题.

Anyway, I think what you're doing now with Assert.IsTrue(a.Object.Equals(b.Object)); and IEquatable is a sufficient workaround for this.

顺便说一句,就像上面的JaredPar所问的那样,为什么要比较模拟呢?

By the way, as JaredPar asked above, why are you comparing mocks?

这篇关于Moq Equals仅适用于IEquatable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆