Moq установка путаницы в C # - PullRequest
0 голосов
/ 26 ноября 2009

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

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

А проверка не удалась. Я проверил, и код вызывает метод real B (), а не метод фиктивного метода B ().

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

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

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

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

Ответы [ 4 ]

7 голосов
/ 26 ноября 2009

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

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

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

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

Это делает внутреннее доступным для генератора кода Moq.

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

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

    [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
    

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

2 голосов
/ 30 декабря 2009

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

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

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

0 голосов
/ 05 февраля 2010

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

var testObject= new Mock<MyClass> { CallBase = true };
0 голосов
/ 26 ноября 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...