Вопрос

Итак, у меня есть следующий класс:

public class MyClass {
  internal void A() {
    foreach(Thing thing in ThingArray)
      B(thing);
  }

  virtual internal void B(Thing thing)
  {
    //  do some stuff
  }
}

И тогда у меня есть следующий тест:

...
var testObject = new Mock<MyClass>(parameters);
testObject.Setup(t => t.B(It.IsAny<Thing>()));

test.Object.A();

test.Verify(t => t.B(It.IsAny<Thing>()), Times.Exactly(2));

И проверка не работает.Я проверил, и код вызывает настоящий Метод B() в отличие от высмеиваемого метода B().

У меня работает много кода, где Moq работает отлично, и я программирую достаточно долго, чтобы понять, что, должно быть, делаю здесь что-то не так, но хоть убей, я этого не вижу.Я исходил из предположения, что, поскольку я вызываю test.Объект.A(), вызовы B() не проходят через Mock, но для меня это не имеет никакого смысла, поскольку вызов из любого другого объекта будет работать так же...

Так почему же не выполняется ложная установка?

Редактировать:Да, у меня есть внутренности, видимые для тестового проекта.Я хотел поместить это в исходный пост, так как знал, что кто-то об этом упомянет.

Что касается реального кода, то, к сожалению, он ОЧЕНЬ проприетарный, поэтому я не могу его опубликовать.Завтра посмотрю, смогу ли я откорректировать код, чтобы он действительно скомпилировался.

Это было полезно?

Решение

Я не уверен, что ответ Гамлора работает. Похоже, что если вы хотите выполнить настройку метода, в котором вы хотите убедиться, что Class1.MethodA вызывает Class1.MethodB, метод MethodB (который вы будете выполнять настройку) должен быть открытым (независимо от InternalsVisibleTo). Я написал простой тест в аналогичной ситуации и обнаружил, что как только я опубликовал свой MethodB, Moq начал работать. Готов поспорить, что если вы сделаете ваш метод B публичным, он сработает.

Я предполагаю, что это ошибка Касла или Мока, но я точно не знаю. Надеюсь, кто-нибудь присоединится.

Я знаю, что публикация MethodB не является хорошим выбором. Но это то, что я знаю о ситуации ...

Другие советы

Объект, который ваш Mock должен соответствовать этим критериям, чтобы успешно имитировать метод:

  • Это должен быть интерфейс
  • Или метод, который вы хотите имитировать, должен быть виртуальным и общедоступным.

Теперь вы также можете имитировать виртуальный внутренний метод, но для этого вам необходимо предоставить Moq доступ к вашим внутренним компонентам.Это вы можете сделать с помощью:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

Это сделает внутреннюю информацию доступной для генератора кода Moq.

Итак, чтобы посмеяться над вашим MyClass.A позвоните, вам нужно сделать это:

  1. Сделайте метод А виртуальным.
  2. И сделайте свой метод общедоступным или разрешите доступ с помощью

    [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
    

Или, как уже было сказано, создайте интерфейс, который представляет API MyClass.

Moq не переносит существующий код, а создает пустой макет.

Это означает, что вызов testObject.Object.A () не выполняет ваш исходный код, поэтому B никогда не вызывается.

Если вы притворяетесь, что вы имитируете интерфейс, то это имеет смысл, потому что у интерфейсов нет кода, так что и у нас не будет макета.

Попробуйте создать макет следующим образом (я не пробовал, поэтому не знаю, работает ли он):

var testObject= new Mock<MyClass> { CallBase = true };
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top