Moq Equals仅适用于IEquatable [英] Moq Equals Only Works With 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屋!