Что такое строгие и нестрогие насмешки?

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

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

14
задан Sandbox 28 June 2010 в 16:23
поделиться

3 ответа

Я не уверен насчет moq конкретно, но вот как строгие mocks работают в 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 рекомендует избегать строгих моков (и предпочитать заглушки), потому что обычно вы не хотите, чтобы ваш тест провалился при получении неожиданного вызова, как указано выше.Это значительно усложняет рефакторинг вашего кода, когда вам нужно исправить десятки тестов, основанных на точном исходном поведении.

13
ответ дан 1 December 2019 в 13:58
поделиться

Вы когда-нибудь сталкивались с Given / When / Then?

  • Given a context
  • When I perform some events
  • Then an outcome should occur

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

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

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

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

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

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

  • non-strict mock: обычно
  • strict mock: желательно никогда

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

3
ответ дан 1 December 2019 в 13:58
поделиться

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

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 для трех коллабораторов, чтобы проверить login(username). Я не вижу, как Strict Mocks никогда не должны использоваться.

0
ответ дан 1 December 2019 в 13:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: