最小起订量等于仅适用于IEquatable
本文关键字:于仅 适用于 IEquatable | 更新日期: 2023-09-27 18:35:53
我正在使用Moq框架进行单元测试,我遇到了这个有趣的问题。
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。
您可能会认为它失败了,因为安装程序只设置 IEquality.Equals() 函数(Assert.AreEqual
可能不会检查),但如果添加该行
a.Setup(x => x.Equals((object)b.Object)).Returns(true);
对于构造函数,它仍然失败。
第二期
如果从接口声明中注释掉: IEquatable<Bar>
(以便a.Setup
覆盖object.Equals
),则两个测试都将失败。
我想要的结果是能够在Mock
对象上设置等于并调用Assert.AreEqual
。
第一期
通过点皮克检查。 Assert.AreEqual
调用静态方法object.Equals
来比较实例。 object.Equals
首先使用operator ==
,由于模拟实例不实现该运算符,因此这将默认为比较引用。显然,a 和 b 是不同的实例,因此比较返回 false。
第二期
我没有看过 Moq 的内部结构,但我认为发生这种情况是因为接口没有声明 Equals 方法。已通过以下方法确认(成功):
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,这个问题可以通过这个问答来解释。
无论如何,我认为您现在正在对Assert.IsTrue(a.Object.Equals(b.Object));
和IEquatable
所做的是足够的解决方法。
顺便说一句,正如 JaredPar 上面问的那样,你为什么要比较模拟?
我用过..
mockLine2.CallBase = True
为什么呢?
我们正在测试订单服务。由于订单有两行,服务将删除与某些条件匹配的任何行。行是一个 IList,List (etc) 使用 .equals() 来查找你想要的项目,所以要删除该行,你需要一个通过的 equals 实现:
Assert.IsTrue(mockLine2.Object.Equals(mockLine2.Object)
"Moq mock 没有检测到一条线等于自己,因此订单上的行集合将无法找到该行。"
你可能会争辩说,由于 Order 不是被测试的类,我们应该嘲笑 Order 并断言order.Lines.Remove()
是用正确的行调用的,但我们发现总的来说,使用真正的域对象(它们都相当愚蠢)比模拟它们更痛苦。