【发布时间】:2016-02-15 10:05:06
【问题描述】:
我有一个有趣的问题要解决。考虑一些像这样的界面:
public interface IMyThing
{
int Id { get; }
}
现在我想测试使用这个接口的代码。也许有一些 LINQ 魔法。像这样的:
public class SomeClass
{
private IMyThing _thing;
...
public bool HasThing(IEnumerable<IMyThing> things)
{
return things.Contains(_thing);
}
}
我正在模拟所有使用Moq 实现IMyThing 的对象:
public static IMyThing MockMyThing(int newId)
{
var mock = new Mock<IMyThing>();
mock.Setup(s => s.Id).Returns(newId);
mock.Setup(s => s.Equals(It.IsAny<object>())).Returns<object>(obj =>
{
if (typeof(IMyThing).IsAssignableFrom(obj.GetType()))
{
return ((IMyThing)obj).Id == newId;
}
return false;
});
return mock.Object;
}
事情就是这样。上面的代码编译时没有警告,但永远不会工作。 Moq 为 Equals() 方法创建了一个拦截器,但它永远无法到达。而是调用对象代理的 equals 方法。我责怪我在模拟一个接口而不是一个具体的类。
更新:刚刚意识到Moq 甚至没有创建拦截器。
当然,我可以像这样扩充IMyThing 界面:
public interface IMyThing : IEquatable<IMyThing>
{
int Id { get; }
}
LINQ 运算符将识别IEquatable<T> 接口并使用它。
我不想这样做,因为:
- 这仅适用于其他
IMyThing对象 -
IEquatable<T>并非用于此目的 - 我不想污染我的模型只是为了让它可模拟
你会怎么解决这个问题?
【问题讨论】:
-
如果你在
HasThing()方法中尝试测试一些复杂的场景,也许它应该接受IEnumerable<IMyThing>。为什么不“引入额外的间接层”?