我有一个有趣的问题需要你思考。考虑这样一个界面:
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()
方法创建了拦截器,但从未被调用。相反,对象代理的等式方法被调用了。我认为这是因为我在模拟一个接口而不是具体类。
更新:刚意识到Moq
甚至没有创建拦截器。
当然,我可以像这样增强IMyThing
接口:
public interface IMyThing : IEquatable<IMyThing>
{
int Id { get; }
}
LINQ操作符将识别IEquatable<T>
接口并使用它。
我不想这样做,因为:
- 这只能与其他
IMyThing
对象一起使用 IEquatable<T>
不是为此目的而设计的- 我不想玷污我的模型,只是为了使其可模拟
你会如何解决这个问题?
HasThing()
方法中测试一些复杂的场景,也许它应该接受IEnumerable<IMyThing>
。为什么不“引入额外的间接层”呢? - shay__