2013-02-20 3 views
9

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

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

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

Это кажется мне плохой.

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

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

ответ

7

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

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

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

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

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

+1

Очень верно, много моих интерфейсов, например. 'IRequestor', опишите, что он делает;) –

3

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

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

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

+2

Согласен с преимуществами модульного тестирования;) Интересная статья о том, почему у C# нет методов экземпляра, которые по умолчанию являются виртуальными: http://geekswithblogs.net/madhawa/archive /2006/09/17/91418.aspx –

+0

Прохладная ссылка, спасибо! – Ben

2

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

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

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

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

+1

Есть хороший вопрос о том, что касается последней части вашего ответа: [Используют ли интерфейсы Soley для облегчения обрезания и издевательств в модульных тестах теперь устарели?] (Http://stackoverflow.com/q/3869002/945456) –

Смежные вопросы