我认为应该是一个非常简单的测试用例,但每次运行它时QTAgent32都会死掉。在调试模式下运行测试用例会在“未知模块”中显示System.StackOverflowException
。我已将其缩小到展示此行为的最基本实现(.NET 4和VS 2010 Ultimate):
[TestClass]
public class StackOverflow
{
[TestMethod]
public void CreateStackOverflow()
{
var mockMyType1 = new Mock<MyType>();
mockMyType1.Setup(m => m.Equals(mockMyType1.Object)).Returns(true);
var mockMyType2 = new Mock<MyType>();
// Real test is for a filtering routine and the Assert is using
// Contains(), but it uses Equals() internally so it has the same problem
Assert.IsTrue(mockMyType1.Object.Equals(mockMyType1.Object)); // returns true
Assert.IsFalse(mockMyType1.Object.Equals(mockMyType2.Object)); // explodes
}
}
public class MyType
{
public virtual bool IsActive { get; set; }
public override bool Equals(object obj)
{
return false; // Not the real implementation but irrelevant to this issue
}
}
我觉得我错过了一些关于闭包或Moq的重要信息,但似乎这应该有效。我尝试过的事情,试图理解这个问题,但只是让我更加困惑:
mockMyType.Setup(m => m.Equals(m)).Returns(true);
替换Equals()设置,但这会导致Moq抛出NotSupportedException 有人能指出我可能发生的事情的方向吗?我完全不知所措。
编辑:我相信我有两个选项来完成这项工作(包括Lanorkin的回复),但我真的很想知道为什么会这样。我做错了什么,或者我应该提交Moq或Visual Studio中的错误?
更新:我最终使用了以下版本的Denys解决方案,并提交了bug report to Moq。我的设置现在看起来像:
mockMyType1.Setup(m => m.Equals(It.Is<MyType>(x => ReferenceEquals(x, mockMyType1.Object)))).Returns(true);
答案 0 :(得分:3)
是的,模拟Equals(对象)使其失败(使用Reflector / dotPeek查看更多内容):
好消息 - 解决方法很容易。只需将Equals重载添加到MyType
类,即可模拟Equals(MyType)
而不是Equals(object)
:
public virtual bool Equals(MyType obj)
{
return Equals((object)obj);
}
答案 1 :(得分:1)
我认为问题在于:
mockMyType.Setup(m => m.Equals(mockMyType.Object)).Returns(true);
仅对相同对象的参数进行模拟。如果您使用任何其他参数,则无法匹配。
请尝试改为:
mockMyType.Setup(m => m.Equals(It.IsAny<MyType>())).Returns(true);
但是,您应该获得有关意外方法调用的其他异常。
答案 2 :(得分:1)
这个问题从昨天开始扰乱了我,最后我找到了答案。您必须在setup方法中使用一个函数,它应该断言模拟对象的真实相等性。我的意思是ReferenceEquals
。所以我修改了你的GetMockMyTypes
代码。当然它不能作为参考,但到目前为止意图很清楚:
public static class MyTypeHelper
{
public static IList<MyType> GetMockMyTypes()
{
var myTypes = new List<MyType>();
var myMock1 = new Mock<MyType>().Object;
Mock.Get(myMock1)
.Setup(m => m.Equals(It.Is<MyType>(x => ReferenceEquals(x, myMock1))))
.Returns(true);
Mock.Get(myMock1).Setup(m => m.IsActive).Returns(false);
myTypes.Add(myMock1);
var myMock2 = new Mock<MyType>().Object;
Mock.Get(myMock2)
.Setup(m => m.Equals(It.Is<MyType>(x => ReferenceEquals(x, myMock2))))
.Returns(true);
Mock.Get(myMock2).Setup(m => m.IsActive).Returns(true);
myTypes.Add(myMock2);
return myTypes;
}
}