Подтвердить что ты не робот

Что такое строгие и нестрогие издевательства?

Я начал использовать moq для насмешек. Может ли кто-нибудь объяснить мне понятие строгих и нестрогих издевательств? Как их можно использовать в moq? ​​

изменить в каком сценарии мы используем какой тип макета?

4b9b3361

Ответ 1

Я точно не знаю о моке, но вот как работают строгие макеты в Rhino. Я объявляю, что ожидаю вызов foo.Bar моего объекта foo:

foo.Expect(f => f.Bar()).Returns(5);

Если вызывающий код делает

foo.Bar();

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

Однако, если код вызова:

foo.Quux(12);
foo.Bar();

тогда мое ожидание потерпело неудачу, потому что я явно не ожидал вызова foo.Quux.

Подводя итог, строгий макет не срабатывает немедленно, если что-то отличается от ожиданий. С другой стороны, нестрогий макет (или заглушка) с радостью "игнорирует" вызов foo.Quux, и он должен возвращать default(T) для типа возврата T из foo.Quux.

Создатель Rhino рекомендует избегать строгих макетов (и предпочитает заглушки), потому что вы обычно не хотите, чтобы ваш тест терпел неудачу при получении неожиданный вызов, как указано выше. Это делает рефакторинг вашего кода намного сложнее, когда вам нужно исправить десятки тестов, основанных на точном оригинальном поведении.

Ответ 2

Когда-либо сталкивались с данными /When/Then?

  • Учитывая контекст
  • Когда я выполняю некоторые события
  • Затем должен произойти исход

Этот шаблон появляется в сценариях BDD, а также подходит для модульных тестов.

Если вы настраиваете контекст, вы будете использовать информацию, предоставляемую этим контекстом. Например, если вы ищете что-то по идентификатору, этот контекст. Если он не существует, тест не будет работать. В этом случае вы хотите использовать режим NiceMock или Stub или любой другой - Moq по умолчанию.

Если вы хотите проверить результат, вы можете использовать проверку Moq. В этом случае вы хотите записать соответствующие взаимодействия. К счастью, это также способ запуска по умолчанию Moq. Он не будет жаловаться, если что-то случится, что вас не интересует этот тест.

StrictMock существует, когда вам не нужны неожиданные взаимодействия. Это то, как использовались старые фальшивые рамки старого стиля. Если вы делаете примеры стиля BDD, вы, вероятно, этого не захотите. Он имеет тенденцию делать тесты немного хрупкими и трудными для чтения, чем если вы отделяете аспекты поведения, которое вас интересует. Вы должны установить ожидания как для контекста, так и для результата, для всех результатов, которые будут происходить независимо от того, интересуются ли они или нет.

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

За последние четыре года я не нашел ни одного примера, который требовал бы использования строгой макеты - либо это был результат, который я хотел проверить (даже если я проверяю количество раз, когда он вызывал), либо контекст для что я могу сказать, правильно ли я отвечаю на предоставленную информацию. Поэтому в ответ на ваш вопрос:

  • нестрогий макет: обычно
  • строгий макет: желательно никогда

NB: я сильно склонен к BDD, поэтому ядро ​​TDDers может не согласиться со мной, и это будет правильно для того, как они работают.

Ответ 3

Здесь хороший article.
Обычно я получаю что-то вроде этого

public class TestThis {

    private final Collaborator1 collaborator1;
    private final Collaborator2 collaborator2;
    private final Collaborator2 collaborator3;

    TestThis(Collaborator1 collaborator1, Collaborator2 collaborator2, Collaborator3 collaborator3) {
        this.collaborator1 = collaborator1;
        this.collaborator2 = collaborator2;
        this.collaborator3 = collaborator3;
    }

    public Login login(String username) {
        User user = collaborator1.getUser(username);
        collaborator2.notify(user);
        return collaborator3.login(user);
    }

}

... и я использую Strict mocks для 3-х сотрудников для проверки входа (имя пользователя). Я не вижу, как Strict Mocks никогда не следует использовать.

Ответ 4

У меня есть простая конвенция:

  • Использовать строгие макеты, когда тестируемая система (SUT) делегирует вызов базовому слоганному слою, не изменяя или применяя какую-либо бизнес-логику к аргументам, переданным самому себе.

  • Использовать свободные макеты, когда SUT применяет бизнес-логику к аргументам, переданным самим себе, и передает некоторые производные/измененные значения на посмеянный уровень.

Например: Допустим, у нас есть провайдер базы данных StudentDAL, который имеет два метода:

Интерфейс доступа к данным выглядит примерно так:

public Student GetStudentById(int id);
public IList<Student> GetStudents(int ageFilter, int classId);

Реализация, которая потребляет этот DAL, выглядит следующим образом:

public Student FindStudent(int id)
{
   //StudentDAL dependency injected
   return StudentDAL.GetStudentById(id);
   //Use strict mock to test this
}
public IList<Student> GetStudentsForClass(StudentListRequest studentListRequest)
{
  //StudentDAL dependency injected
  //age filter is derived from the request and then passed on to the underlying layer
  int ageFilter = DateTime.Now.Year - studentListRequest.DateOfBirthFilter.Year;
  return StudentDAL.GetStudents(ageFilter , studentListRequest.ClassId)
  //Use loose mock and use verify api of MOQ to make sure that the age filter is correctly passed on.

}