鉴于此代码:
[ContractClass(typeof(DogContract))]
public interface IDog {
void Eat(object obj);
}
[ContractClassFor(typeof(IDog))]
internal abstract DogContract : IDog {
public void Eat(object obj) {
Contract.Requires<ArgumentNullException>(obj != null);
}
}
var dogMock = new Mock<IDog>();
dogMock.Object.Eat(null); // Throws ArgumentNullException
似乎重写器以某种方式将其行为放入模拟对象中,这是我没想到的。我不认为这是一个真正的问题,只是出乎意料。谁知道这是怎么回事?
答案 0 :(得分:1)
“呼叫站点需要检查”将执行此操作。然后,重写器将先决条件放入调用者代码而不是实现。因此,即使模拟对象中的代码不能被重写(它是在运行时生成的),调用者中的代码也可以。
以下是没有调用站点需要的生成代码:
private static void Main(string[] args)
{
Mock<IDog> m = new Mock<IDog>();
m.Object.Eat(null);
}
并且:
private static void Main(string[] args)
{
Mock<IDog> m = new Mock<IDog>();
IDog.V$Eat(m.Object, null);
}
IDog是一个静态类,它包含IDog接口中的所有方法以及前提条件。以下是Eat的样子:
internal static void V$Eat(IDog @this, object obj)
{
__ContractsRuntime.Requires<ArgumentNullException>(
obj != null, null, "obj != null");
@this.Eat(obj);
}
这样,即使无法重写类中的代码,也会调用前置条件。