2012-05-31 44 views
3

我使用Moq框架进行单元测试,并且遇到了这个有趣的问题。Moq Equals只适用于IEquatable

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

+4

为什么你想比较模拟生成的对象'Mock '? – JaredPar

+0

要以不同的方式询问@ JaredPar的问题,测试的对象/单元是什么? – manojlds

+0

它是在另一个类上测试一个相等运算符。这个功能一直没有成功,所以我进入它并注意到两者并不像我想的那样平等。 – hehewaffles

回答

4

第一个问题

通过dotPeek经过。 Assert.AreEqual调用静态方法object.Equals来比较实例。 object.Equals首先使用operator ==,并且由于模拟实例没有实现该运算符,所以默认情况下会比较引用。显然,a和b是不同的实例,所以比较返回false。

第二期

我还没有看起订量的内部,但我想这是因为接口不声明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以来,这个问题可以用Q&A来解释。

无论如何,我认为你现在在做什么,Assert.IsTrue(a.Object.Equals(b.Object));IEquatable是一个充分的解决方法。顺便说一下,正如JaredPar上面所述,为什么你要比较模拟?

1

我用..

mockLine2.CallBase = True 

,为什么?

我们正在测试订单服务。 由于订单有两行,服务会删除符合某些条件的任何行。 线是IList,列表(等)使用。equals()方法来找到你想要的物品,所以要去除线,你需要平等的实现,通过:

Assert.IsTrue(mockLine2.Object.Equals(mockLine2.Object) 

“起订量模拟没有检测到线等于本身,所以网上收集上“)

你可能会争辩说,因为Order不是被测试的类,所以我们应该嘲笑这个命令并且声明order.Lines.Remove()被调用了右边的行,但是我们已经发现它了总的来说,使用真实的域对象(他们都相当愚蠢)比嘲笑他们更少的痛苦。