Часто говорят, что интерфейсы делают насмешливое и модульное тестирование более легким процессом. Как с этим справляются интерфейсы?
Как интерфейсы упрощают модульное тестирование и насмешливость?
Ответ 1
Это характер интерфейсов обеспечивает множество реализаций, таким образом, позволяет насмехаться.
В частности, при тестировании интеграции вы можете предоставить свою версию макета системы зависимостей (например, веб-сервис). Вместо фактического вызова зависимой системы или даже модуля или сложного и сложного для создания типа вы можете предоставить простейшую реализацию интерфейса, которая предоставит необходимые результаты для unit test для правильной.
В дополнение к этому , когда вы используете при модульном тестировании, фактический зависимый тип (назовите его BigGraph), скрывая за собой сложную объектную модель, вы на самом деле интеграционное тестирование, а не модульное тестирование. Тестовый тест можно легко сломать, если есть ошибка в любом из зависимых типов (BigGraph), а не в том типе, который вы тестируете, а не в модульном тестировании. Использование макетов уменьшает риск этого.
Я видел много систем непрерывной интеграции, показывающих десятки ошибок для одной ошибки, когда они должны отображать одну или, самое большее, пару, из-за слишком сложных объектных моделей и неправильно написанного модульного теста - не используя mock -ups.
Сегодня издевательские фреймворки более сложны (модификация байт-кода и т.д.), чем старые, поэтому иногда интерфейсы или даже виртуальные методы не всегда нужны, но их поддерживают безжизненные интерфейсы.
Интерфейсы не помогут, если ваша объектная модель слишком сложна и захламлена (например, ваш интерфейс в значительной степени зависит от других типов/интерфейсов); то реализация/издевательство над этим - это боль.
Ответ 2
Если у вас есть несколько объектов, которые имеют другую реализацию, но предлагают одни и те же методы для совместного использования сторонними интерфейсами, вы можете написать один unit test и запустить его во всех реализациях.
Если у вас есть класс, в котором говорится о материалах сообщений на веб-конце, а затем извлекается тестирование единицы ответа, что было бы проблематично, потому что неудавшееся интернет-соединение могло позволить вашему тесту выйти из строя. Поэтому вы определяете интерфейс для этого класса, а затем можете написать вторую реализацию, которая регистрирует материал, который должен быть отправлен, и доставляет правильный ответ. Таким образом, вы можете протестировать классы, которые работают с ответом с обратной стороны, не полагаясь на подключение к Интернету во время тестового запуска.
Ответ 3
Если у вас есть класс, у вас может быть множество зависимостей, например
-
Конструкторы insane (много аргументов или нужны некоторые другие классы, которым нужен третий класс, которому нужен четвертый класс, который должен иметь действительное соединение с базой данных)
-
Чтобы использовать класс каким-либо образом, вы должны его инициализировать правильно (например, вы должны передать ему и другие объекты, которые также должны быть действительными)
-
Класс имеет состояние. По какой-либо причине это состояние может измениться во время теста.
-
Класс может иметь или использовать статические поля
Эти зависимости обычно неактуальны во время многих ваших тестов, и вам больше не придется иметь дело с ними.
С помощью интерфейса вы можете создать простой класс mock, который просто реализует несколько методов, которые вам нужны. У большинства насмешливых фреймворков есть встроенная поддержка для этого. "Реализация" здесь обычно означает "вернуть фиксированное значение". Таким образом, вы можете быстро создать среду, в которой нуждается тестируемый класс.
Так, например, если вашему классу нужно читать записи из базы данных, вы можете вместо этого выкрикнуть ResultSet
, который просто возвращает строки. Следовательно, вам не нужно иметь реальную базу данных, вам не нужно создавать соединение (которое медленно и может не работать по многим причинам), вам не нужно заботиться о данных в базе данных (так что вы не 't нужно удалить/удалить таблицы и снова заполнить их тестовыми данными) и т.д.
Ответ 4
Если вы не привязаны к конкретной реализации, вы можете переключать поведение за интерфейсом.
Если ваши классы реализуют интерфейсы, поведение можно издеваться.
Например, вам не нужно спамить всех своих клиентов в своей базе данных, чтобы проверить, работает ли ваш алгоритм уведомления по электронной почте. Вы создадите макет для вашего интерфейса IMailSender
и будете только подсчитывать количество отправленных сообщений электронной почты. Затем вы проверите фактическую реализацию, которая фактически отправит электронные письма на один адрес электронной почты, и вы знаете, что работает весь процесс уведомления.
В этом конкретном примере в тесте используется mock-реализация IMailSender
, которая учитывает только отправленные сообщения и ваш фактический производственный код будет использовать реализацию реализации IMailSender
, которая фактически отправляет электронные письма через SMTP-сервер.
Ответ 5
При тестировании поведения, пересекающего порт, наличие интерфейса для адаптера поможет внедрить другую реализацию во время тестирования (например, test double).
Например, DAO, который вызывает базу данных или веб-службу, может быть заменен реализацией, которая возвращает зашифрованные данные.