Что такое строгие и нестрогие издевательства? - PullRequest
14 голосов
/ 28 июня 2010

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

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

Ответы [ 4 ]

13 голосов
/ 28 июня 2010

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

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

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

foo.Bar();

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

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

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

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

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

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

3 голосов
/ 28 июня 2010

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

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

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

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

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

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

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

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

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

NB. Я сильно склонен к BDD, поэтому жесткие TDD-устройства могут со мной не согласиться, и это будет правильным для их работы.

0 голосов
/ 22 октября 2013

У меня есть простое соглашение:

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

  2. Используйте свободные макеты, когда 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.

}
0 голосов
/ 30 июня 2010

Вот хорошая статья .
У меня обычно бывает что-то вроде этого

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

}

... и я использую строгие макеты для трех соавторов, чтобы проверить логин (имя пользователя). Я не понимаю, как никогда нельзя использовать Строгие Насмешки.

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