Moq正在解雇代码合同?

时间:2012-01-09 17:28:39

标签: c# .net-4.0 moq code-contracts

鉴于此代码:

[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

似乎重写器以某种方式将其行为放入模拟对象中,这是我没想到的。我不认为这是一个真正的问题,只是出乎意料。谁知道这是怎么回事?

1 个答案:

答案 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);
}

这样,即使无法重写类中的代码,也会调用前置条件。