Tom*_*mas 3 unit-testing moq equals mocking
使用精细的模拟框架MoQ,我遇到了一个有点令人惊讶的方面(我不喜欢惊喜).我正在嘲笑一个应该在方法调用后添加到集合中的类,如下所示:
public class SomeClass{
}
public class Container {
private List<SomeClass> classes = new List<SomeClass>();
public IEnumerable<SomeClass> Classes {
get {
return classes;
}
}
public void addSomeClass(SomeClass instance) {
classes.Add(instance);
}
}
[Test]
public void ContainerContainsAddedClassAfterAdd() {
var mockSomeClass = new Mock<SomeClass>();
mockSomeClass.Setup(c => c.Equals(mockSomeClass.Object)).Return(true);
var Container = new Container();
Container.addSomeClass(mockSomeClass.Object);
Assert(Container.Classes.Contains(mockSomeClass.Object));
}
Run Code Online (Sandbox Code Playgroud)
这很好用,模拟被添加到Container集合中,并且Equals模拟方法的设置确保IEnumerable.Contains()返回true.然而,总有一些复杂因素.我真正嘲笑的课程并不像我们那么简单SomeClass.它是这样的:
public class SomeClassOverridingEquals{
public virtual Equals(SomeClassOverridingEquals other) {
return false;
}
public override Equals(object obj) {
var other = obj as SomeClassOverridingEquals;
if (other != null) return Equals(other); // calls the override
return false;
}
}
[Test]
public void ContainerContainsAddedClassOverridingEqualsAfterAdd() {
var mockSomeClass = new Mock<SomeClassOverridingEquals>();
mockSomeClass.Setup(c => c.Equals(mockSomeClass.Object)).Return(true);
var Container = new Container();
Container.addSomeClass(mockSomeClass.Object);
Assert(Container.Classes.Contains(mockSomeClass.Object)); // fails
}
Run Code Online (Sandbox Code Playgroud)
该类包含对其自己的特定类型的Equals方法的覆盖,并且Setupmock 的方法似乎无法模拟该特定方法(仅覆盖更一般的方法Equals(object)).因此测试失败.
到目前为止,我还没有办法解决这个相当普遍的模式,除了重写类不使用重写的等号.
我不喜欢那样.
有人有主意吗?
我不认为问题出在Moq上,而是使用Contains扩展方法.即使您使用更具体的重载重载了Equals,Enumerable.Contains最终List<T>.Contains也会调用,因为Classes属性实际上是由a支持的List<T>.
List<T>.Contains通过调用实现EqualityComparer<T>.Default.Equals,我认为这默认调用从System.Object继承的Equals方法 - 即:不是你的模拟覆盖的那个,而是将System.Object作为输入的那个.
仔细阅读EqualityComparer<T>.DefaultReflector中的实现,似乎它有类型实现的特殊情况IEquatable<T>,因此如果将该接口添加到类(它已经有适当的方法),它可能表现不同.
| 归档时间: |
|
| 查看次数: |
1473 次 |
| 最近记录: |