Важна ли разница между разными тестовыми двойниками?

Я как раз читал сообщение Мартина Фаулера Mocks Aren't Stubs. Он определяет различные тестовые двойники (или, скорее, ссылается на книгу шаблонов xUnit Джерарда Месароса):

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

Первая часть моего вопроса: действительно ли это авторитетно? Широко ли используется и понят этот язык?

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

  • Все называется «макетом». Вызывая метод Mockito.mock () или используя аннотацию @Mock, вы используете слово «mock» для создания mock-объектов, заглушек, а иногда и фиктивных (если простое «новое» не подойдет). Исключением является «шпион», который может быть использован для создания чего-то вроде «подделки», но может также использоваться для обертывания тестируемой системы.
  • Даже если вас не волнует имя метода для создания тестового двойника, этот дубль можно проверить (или нет), и вы можете включить захват на этапе проверки, который, похоже, включает некоторые вещи, которые будет делать заглушка. (запоминание сделанных звонков) и имитация (проверка того, что были сделаны определенные ожидаемые звонки).

Причина, по которой я спрашиваю, заключается в том, что я пытаюсь назвать своих двойников в соответствии с четырьмя вещами, которые я вижу выше, но затем иногда путаюсь, действительно ли что-то играет роль заглушки или имитации. Итак, это недостаток Mockito, или это просто то, как все развивались, и различие на самом деле не важно?


person jhericks    schedule 11.01.2012    source источник
comment
Разница значительна, если вы воспользуетесь ею в своих интересах. Когда я вижу макет, я знаю, что в центре внимания теста находится зависимость. Я внимательно смотрю на это. Когда я вижу заглушку, я знаю, что могу спокойно ее проигнорировать ... это просто что-то, что нужно вставить, чтобы тест работал - второстепенная деталь. Я был бы удивлен, если бы увидел какие-либо утверждения / ожидания в отношении заглушки. Вы можете улучшить читаемость ваших тестов, правильно указав зависимость как заглушку или макет.   -  person Gishu    schedule 12.01.2012


Ответы (3)


Английское слово «mock» означает «имитация более низкого качества, чем оригинал». Вот почему даже скрученные вручную макеты (написанные без помощи фреймворка, такого как Mockito) иногда называют макетами.

Язык, который использовал Мартин, теперь немного устарел. Он написал это в контексте старых фреймворков для создания макетов, таких как JMock, до того, как появились «красивые макеты». В то время издевательства были строгими; любые взаимодействия, которые не были настроены и не ожидались, потерпят неудачу.

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

Моки заменяют этих соавторов, и мы больше не склонны использовать ожидания в отношении имитаторов. Вместо этого мы настраиваем макеты для предоставления информации, а затем проверяем, что им было предложено выполнить любую работу, которая должна быть выполнена. Mockito был первым фреймворком, который работал таким образом, и поэтому различие размыто - потому что, что бы вы ни делали, вы издеваетесь над соавтором, и вам больше не нужно устанавливать ожидания. Moq работает точно так же в .NET.

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

Кроме того, поскольку Mockito предоставляет «хорошие» mock-объекты, вам не нужно беспокоиться об установке ожиданий на случай, если где-то будет использоваться фиктивный объект - вы также можете просто использовать Mockito для их создания. И, на всякий случай, если вы хотите добавить какое-то простое поведение, Mockito позволяет вам легко выполнять обратные вызовы для аргументов, которые ему передаются, так что вы можете создавать «Подделки».

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

Ранние фреймворки не обеспечивали такой гибкости, отсюда и дифференциация Мартина, призванная помочь вам правильно использовать макеты. Надеюсь, это поможет прояснить ситуацию и объяснить, почему гибкость Mockito не является недостатком, но - как указал Дэвид Уоллес - сила.

person Lunivore    schedule 11.01.2012
comment
Я не уверен насчет jMock 1, но jMock 2 определенно обеспечивает гибкость создания хороших макетов с помощью метода allowing(mock). - person Rogério; 12.01.2012
comment
Да, теперь это так. Этого не было в те дни, когда был создан Mockito, и, конечно, не по умолчанию. Стив Фриман и Нат Прайс создали JMock с немного другим мышлением. Стив говорит мне, что строгие mock'ы служат совсем другой цели, чем такие вещи, как Mockito, будучи более явными. Я отчасти понял и пообещал признать вклад Стива, Ната и JMock в мир насмешек ... при этом все еще действительно, очень предпочитая Mockito. - person Lunivore; 12.01.2012
comment
Несомненно, каждый из нескольких насмешливых API для Java внес что-то важное. Но я подозреваю, что вы действительно имеете в виду свое предпочтение, если для нового стиля проверки взаимодействий в конце тестов (введенного Mockito и называемого некоторыми Arrange-Act-Assert), а не одним конкретным API . Другие имитирующие API теперь предоставляют тот же тип API, например Unitils Mock, который похож на Mockito (за исключением несоответствий). - person Rogério; 13.01.2012
comment
Мы всегда отдаем предпочтение знакомому, что в моем случае означает Mockito. Я уверен, что другие фреймворки для имитации тоже хороши ... хотя я еще никогда не видел ни одного фреймворка, в котором не было бы некоторых несоответствий. - person Lunivore; 14.01.2012
comment
Да, теперь это так. Этого не было в те дни, когда был создан Mockito. Это абсолютно неверно. JMock 1 и jMock 2, оба из которых существовали до Mockito, имели возможность указывать отдельные макеты или все как хорошие. JMock делает это явным вызовом, чтобы привлечь внимание читателя к тому, что невидимые взаимодействия могут происходить за кулисами. - person Nat; 02.09.2012
comment
Нэт, прошу прощения. Однако я все же отмечаю, что это не было по умолчанию. - person Lunivore; 03.09.2012
comment
Похоже, Mockito был разработан до выпуска JMock 2, если даты в дистрибутивах верны (я должен увидеть версию 0.1, которая, как мне кажется, больше не существует!). Я действительно помню, что Щепан написал это, потому что он поймал меня на развертывании моих собственных макетов вместо использования синтаксиса какой-либо из существующих макетов фреймворков, и мы уже попробовали это как часть JBehave 1, так что, возможно, я ' Я неправильно помню, чего не хватало. Спасибо вам и Стиву за исторический вклад, без которого ни то, ни другое не существовало бы. - person Lunivore; 03.09.2012
comment
Посмотрев документацию, все еще кажется, что вам нужно настроить ожидания для JMock, а не просто проверять после этого? Или я что-то упускаю? - person Lunivore; 03.09.2012

Собственно, в этом сильная сторона Mockito. Мок Mockito - это объект, на котором вы можете либо «заглушить» методы, либо «проверить» методы, либо и то, и другое. (Выполнение обоих для одного и того же метода - это своего рода запах кода, но это уже другая тема). Таким образом, макет Mockito - это одновременно «заглушка» (в смысле Мартина Фаулера) и «макет» (в смысле Мартина Фаулера); но вам не обязательно использовать их одновременно. Обычно mockito действует как «заглушка» ИЛИ как «макет»; реже и то, и другое.

В некоторых других макетных фреймворках такого уровня гибкости нет. Если вы хотите выполнить «проверку» на макете, вам также необходимо выполнить «заглушку». В этих фреймворках макеты ДОЛЖНЫ действовать как «заглушка» и как «макеты». Насколько я понимаю, одним из факторов, которые побудили Щепана Фабера к созданию Mockito, было желание разделить поведение «заглушки» и «имитацию» (в строгом понимании обоих слов Мартина Фаулера).

person Dawood ibn Kareem    schedule 11.01.2012
comment
Неужели это запах, когда нужно настраивать вещи, которые вы потом собираетесь проверять? Если вы не настроите их, они возвращают нули, нули, пустоты или пустые списки. Это запах с кодом или запах с тестом? - person jhericks; 12.01.2012
comment
Да, я так считаю. Щепан Фабер написал отличное объяснение почему, но сейчас я не могу его найти. Но все сводится к тому, имеет ли значение результат вызова метода для выполнения теста. Если результат важен для проверяемого состояния, тогда метод необходимо заморозить. В этом случае тест завершится неудачно, если при вызове метода будет предпринято неправильное действие или если метод не будет вызван; что означает, что нет смысла проверять метод. И наоборот, если результат не важен для проверяемого условия, то нет смысла заглушать метод. - person Dawood ibn Kareem; 12.01.2012
comment
Конечно, всегда есть исключения. Если важно точное количество вызовов метода, а также результат вызова метода, вы можете заглушить метод, но также использовать verify, чтобы гарантировать, что метод вызывается один раз, а не дважды; или называется другое указанное количество раз. - person Dawood ibn Kareem; 12.01.2012
comment
Привет. Другой причиной был синтаксис EasyMock (спасибо его изобретателю Анри Трембле), который, кстати, является предком Mockito. Этот синтаксис неудобен; с ожиданием, воспроизведением и прочим словарный запас, а затем раскладка теста была неестественной. Сегодня с mockito вы можете выложить свой тест с использованием подхода AAA или BDD, которые, на мой взгляд, являются более понятным способом выразить ваш тест. - person Brice; 12.01.2012
comment
2 цента ... ИМО, если вы следите за оценкой, что каждый модульный тест должен тестировать одну вещь / поведение, и каждый тест должен быть небольшим, тогда обширная настройка макетов и проверка всего не требуется. С AAA вы настраиваете, как если бы это была заглушка (включая только заглушки, необходимые для прохождения теста), а затем проверяете, что был вызван конкретный метод. Если это то, что вы тестируете, то реальное различие между заглушками и имитаторами заключается в том, как вы пишете модульный тест, а не в том, что фреймворк для фиксации делает что-то по-другому с заглушками и макетами. - person aqwert; 12.01.2012

Согласно тому, что я понял из тестовых шаблонов X-Unit Джерарда Месароса, макет - это тест-двойник, который включает в себя функции манекена, заглушки и шпиона. Вы можете проверить фактическое сравнение, которое он делает о них, на стр. 742 этой книги.

Также эта статья может пролить свет на ваш вопрос. В этой статье четко говорится, что

«Макет динамически создается макетной библиотекой (остальные обычно создаются разработчиком теста с использованием кода). Разработчик теста никогда не видит фактический код, реализующий интерфейс или базовый класс, но может настроить макет для предоставления возвращаемых значений, ожидая конкретные вызываемые члены и т. д. В зависимости от конфигурации макет может вести себя как пустышка, заглушка или шпион ».

введите описание изображения здесь

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

person Bala    schedule 26.01.2012