Moq это контракты на стрельбу код? - PullRequest
1 голос
/ 09 января 2012

Учитывая этот код:

[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 Ответ

1 голос
/ 12 января 2012

«Call-site требует проверки» сделает это. Затем перезаписывающее устройство помещает предварительные условия в код вызывающий , а не в реализации . Таким образом, хотя код в макетируемом объекте не мог быть переписан (он генерируется во время выполнения), код в вызывающей программе может быть.

Вот как выглядит сгенерированный код без call-сайта. Требуется:

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

Таким образом, предварительные условия будут вызываться, даже если код в классе не мог быть переписан.

...