Как избежать дублирования кода при использовании моков в юнит-тестах

Я использую внедрение зависимостей для предоставления имитаций для кода за пределами моего тестируемого класса. Я обнаружил, что пишу один и тот же код снова и снова, поскольку мне нужно высмеивать AuthProvider, ConfigurationManager и т. Д., Которые используются в методе, который я хочу протестировать. Метод содержит ветки (if-then-else), поэтому у меня есть несколько тестов для проверки всех путей выполнения метода. Я создаю экземпляры каждого из макетов несколько раз (по одному в каждом методе тестирования), но мне интересно, не так ли это? Также я возлагаю надежды на макеты и предустановленные ответы, которые, очевидно, в основном являются копипастом, поскольку такие вызовы, как AuthProvider.Authenticate () вызываются в каждом методе

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

Для реализации моков я использую RhinoMocks.


person Fadeproof    schedule 06.01.2009    source источник


Ответы (5)


"создание экземпляров каждого из макетов несколько раз" не проблема. Объекты бесплатны.

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

Кроме того, у вас есть метод «setUp» в TestCase, который позволяет вам создать прибор, который будет использоваться всеми тестами. Да, он перестраивается для каждого теста. Нет, это не проблема, если только это не очень медленно.

person S.Lott    schedule 06.01.2009

Предполагая, что вы используете NUnit, вы можете использовать переменные экземпляра для своих Mocks и сбросить их в Setup / Teardown. Если вы видите повторяющиеся шаблоны, то сделайте то, что вы делаете с производственным кодом: проведите рефакторинг и извлеките вспомогательные методы, которые выражают то, что вы пытаетесь достичь (если нет никакой общности, тогда есть проблема с дизайном производственного кода).

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

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

Послушайте тесты!

person Steve Freeman    schedule 21.05.2009
comment
Большое спасибо за содержательный ответ. Мне интересно, как бы я написал несколько тестовых классов для производственного класса ... как бы я назвал несколько тестовых классов? - person Fadeproof; 29.05.2009
comment
Назовите тестовые классы в честь того, что в них важно - как и все другие классы :) - person Steve Freeman; 30.05.2009

Вот мое мнение ..

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

Моки, я полагаю, следует использовать, когда вы тестируете какое-то динамическое поведение ... что-то вроде ... был ли метод в подсистеме вызван, когда я выполняю какое-то действие над SUT ... и позже вызовите verify (), чтобы проверить это поведение. .. есть также хорошая статья о Мартине Фольвере bliki Mock Aren't Stubs

person StackUnderflow    schedule 06.01.2009

Возможно, вы захотите использовать стиль тестирования AAA, чтобы у вас было несколько тестов с общей настройкой. Вот достойный пример.

person Garry Shutler    schedule 06.01.2009

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

И, возвращаясь к вашей проблеме создания экземпляров Mocks в каждом методе тестирования, есть способ лучше, чем использование метода setUp (). Mockito предоставляет аннотацию @Mock. Итак, вы объявляете свои переменные (как поля), например: @Mock Repository repositoryMock

и просто вызовите initMocks () в setUp (). Все объявленные имитационные объекты автоматически доступны в ваших тестах без явного создания имоков.

person Sathish    schedule 06.01.2009
comment
Фреймворки записи и воспроизведения, такие как EasyMock, не работают, если вы не устанавливаете ожидание для фиктивного вызова. = ›Это неверно. Все имитирующие инструменты, включая EasyMock, позволяют разработчику иметь нестрогие ожидания. В EasyMock вы делаете это, создавая красивый макет с помощью метода createNiceMock (). - person Rogério; 13.08.2009