2015-02-23 8 views
1

У нас есть задача FooTask. Мы создаем класс Foo, который имеет 1 ответственность с точки зрения бизнес-логики. Но оказывается, что FooTask действительно сложный. Он состоит из нескольких шагов/подзадач, которые затем могут быть представлены классами Bar/Baz. Эти классы не имеют реального смысла вне класса Foo, они не будут использоваться исключительно. Таким образом, у них, вероятно, будет область пакета или что-то в этом роде.Составная единица измерения

Итак, пусть ваш класс Foo, представляющий FooTask становится:

public class Foo { 
    private final Bar bar; 
    private final Baz baz; 

    // all-args constructor 

    public ReturnType doFooTask(InputParam input) { 
     final SubResult subresult = bar.doBarSubTask(input); 
     return baz.doBazSubTask(subresult); 
    } 
} 

Теперь, как бы вы проверить это? Я вижу два варианта, но не знаю, какой из них лучше:

1) классы тестов Bar и Baz через открытый API Foo. Я вижу один важный поток с таким подходом: чем больше подпроектов вы используете для создания объекта, тем больше случаев прихода.

2) Напишите полные комплекты тестов для классов Bar и Baz самостоятельно (они являются частными, поэтому я могу протестировать их без каких-либо проблем, как только я сохраню правильную иерархию тестовых пакетов).

Но что тогда? Должен ли я оставить класс Foo непроверенным? Должен ли я повторять свои тесты (это приводит к моей предыдущей проблеме - много тестовых примеров, что еще хуже, скопировать)? Или, может быть, я должен издеваться над всеми зависимостями и просто утверждать, что мой правильный метод на мой макет вызывался при вызове метода Foo?

ответ

3

Начните с написания полных комплектов тестов для баров и базов.

Если Foo действительно тривиальный, как в вашем примере, вы можете не писать тесты для него. Но я бы не хотел оставлять тестируемый код непроверенным, поэтому я бы написал для него тесты. Если вы пишете тесты для Foo, то выполняйте только то, что требуется для проверки Foo. Подход к единичному тестированию обычно заключается в том, чтобы писать интерфейсы для Bar и Baz, а затем издеваться над ними, тогда вы можете использовать некоторую технологию инъекций зависимостей для передачи в mocks. Это определенно подход, который вы хотите сделать, если у Bar and Baz есть другие зависимости, или попытайтесь прикоснуться к файловой системе или поговорить с базой данных или что-то в этом роде, или если они сложны и требуют большой настройки.

Бывают ситуации, когда вам не нужно это делать. Если Bar и Baz достаточно просты и не имеют внешних зависимостей, тогда вы можете написать тест для Foo, который просто использует экземпляры Bar и Baz. Эти тесты, которые вы пишете, будут сосредоточены на том, чтобы убедиться, что поведение, написанное в Foo, работает правильно, и вы пишете с учетом предположения, что Bar и Baz работают правильно, поскольку вы уже написали им модульные тесты. Вы не будете писать тесты, которые охватывают множество комбинаций входов и выходов, поскольку вы уже сделали это для Bar and Baz, вы просто хотите получить освещение в Foo и получить правильную информацию от Bar to Baz при правильных условиях. Это то же количество тестов, которые вы напишете, если бы высмеивали Бар и Баз.

Если «Бар и Баз» являются сложными, требуют большого количества настроек или внешних зависимостей, которые вы должны издеваться или инициализировать, а затем издеваться над ними и просто тестировать Foo с помощью mocks. Кроме того, если использование реальных объектов закончится в вашем модульном тесте, уделив много времени, чтобы запустить, затем издевайтесь над ними.

+0

Да, я знаю, что насмехается и когда его использовать, поверьте мне;) В любом случае - спасибо за ваш ответ. Вопрос был на самом деле: должен ли я предпочесть тестировать ингредиенты самостоятельно или через «основной» класс? – slnowak

+0

Да, это в основном сводится к их индивидуальной сложности. Поскольку они разбиты, я буду писать тесты, которые будут охватывать их индивидуально, а затем использовать их только при необходимости для установки объекта Foo, чтобы вы могли писать тесты, которые охватывают логику в Foo. – Erik

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