Являются ли отдельные интерфейсы реализации для модульного тестирования антипаттерн?

142
18

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


Ну, я чувствую, что нарушаю это правило каждый раз, когда я пытаюсь unit test.


У меня есть класс, встроенный в мою сборку, Xyzzy. Я хочу, чтобы зависимость вводила его в другой класс, а затем заглушала его, поэтому я могу проверить, что другой класс изолирован, поэтому я создаю интерфейс IXyzzy. К сожалению, теперь у меня есть код в производстве, который действительно существует только для теста. Хуже того, я немного против того, что такое интерфейс (описывает, что может сделать разработчик, а не то, что он). Открытый интерфейс Xyzzy и IXyzzy - это точно то же самое, и никто другой (кроме заглушек) не реализует IXyzzy.


Мне кажется, что это плохо.


Я мог бы создать абстрактный базовый класс или сделать все общедоступные методы, которые я хочу проверить на Xyzzy Overridable/virtual, но это тоже не так, поскольку Xyzzy не предназначен для наследования и с точки зрения YAGNI, выиграл 'никогда не унаследовано от.


Создает ли интерфейсы только одного разработчика исключительно для тестирования анти-шаблона? Есть ли лучшие альтернативы?

спросил(а) 2021-01-19T18:17:51+03:00 6 месяцев, 1 неделя назад
1
Решение
126

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


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


Я уже не против того, какой интерфейс (описывает, что исполнитель может сделать, а не то, что он есть)


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


Если вы думаете об этом, каждый класс имеет "интерфейс" в более свободном смысле слова: публичная подпись всех методов предоставляет интерфейс, который класс поддерживает снаружи. Независимо от того, реализован ли интерфейс .NET или нет, это просто деталь. Класс по-прежнему делает тот же promises снаружи.

ответил(а) 2021-01-19T18:17:51+03:00 6 месяцев, 1 неделя назад
90

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


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

Продолжайте делать то, что вы делаете - любой грех, который вы совершаете, на мой взгляд, легко перевешивается преимуществами вашего модульного тестирования!

ответил(а) 2021-01-19T18:17:51+03:00 6 месяцев, 1 неделя назад
78

Да, это анти-шаблон. Шаблон будет "решением общей проблемы в определенном контексте". Но в этом случае у нас есть работа, а не решение.


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


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


Для .NET есть несколько инструментов для издевательств, которые обеспечивают эту изоляционную способность, а именно TypeMock Isolator, JustMock и MS Fakes. Другие языки/платформы (включая Java, Ruby и Python) имеют свои собственные инструменты с аналогичной выразительной способностью.

ответил(а) 2021-01-19T18:17:51+03:00 6 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема