Модульное тестирование, статика и фабрики - PullRequest
6 голосов
/ 12 апреля 2011

Я реализую модель на Java, которая требует итерации по коллекции и прохождения ряда этапов идентификации, включая циклы, циклы и т. Д. Это то, что я хочу протестировать на детальном уровнетак что я уверен, что он был реализован правильно.

Я использовал его как возможность начать модульное тестирование, так как это то, что я считаю полезным для моего кода.С тех пор я читаю лес книг, чтобы освоить JUnit и модульное тестирование.

В основном мой вопрос сводится к двум противоречивым советам, которые я получил:

1) СтатиказлыеНе трогай статику.Не проверяйте и рядовых, вы, вероятно, хотите вместо этого использовать класс.
2) Использовать фабрики для создания, чтобы разрешить внедрение зависимостей с использованием параметров - потенциально позволяя использовать mocks и заглушки для изоляции.

В моем примере IЯ пытаюсь выполнить операцию в соответствии с:

double height = 223.42; // this was set iterating over a collection of doubles
//blah
HeightBounds b = HeightBounds.getHeightBounds(height);
//more blah

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

Здравый смысл говорит мне, что в статических фабриках нет ничего плохого, и что они легко тестируются, но я скучаючто-то ослепительно очевидное, учитывая, что я изучаю дизайн, управляемый тестами?

Спасибо

Ответы [ 5 ]

3 голосов
/ 12 апреля 2011

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

Если вместо этого вы внедрили реализацию IHeightBounds в свой класс, вы можете смоделировать это, чтобы проверить, что происходит, когда зависимости вашего класса делают определенные вещи.

Например, что если HeightBounds выдает исключение? или возвращает ноль? Или вы хотите проверить, когда возвращается конкретный HeightBound? С интерфейсом легко смоделировать это поведение, со статической фабрикой это сложнее, так как у вас есть данные для создания желаемых результатов в классе.

У вас все еще может быть только одна реализация HeightBounds, и вы сможете протестировать ее изолированно, но вы сможете протестировать свой метод выше, даже не имея реальной реализации.

Я бы, вероятно, имел бы интерфейс IHeightBoundFactory и внедрил бы реализацию в класс.

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

Если у вас есть метод с именем Add и метод с именем GetAll, вы можете проверить, что при вызове Add и последующем вызове GetAll вы получите тот, который вы добавили. вам все равно, как это реализовано, только то, что это работает. это проверка результатов. Обычно в этой ситуации вы хотите создать фиктивные объекты, которые возвращают данные. Это похоже на вашу ситуацию.

Если при вызове Add вы ожидаете, что добавляемое записывается в журнал, вы хотите протестировать взаимодействия с зависимостью журналирования, поэтому вы вводите фиктивную зависимость и проверяете, что взаимодействие с этим классом происходило при вызове Add. Как правило, в этой ситуации вы хотите создать фиктивные объекты с установленными ожиданиями и убедиться, что эти ожидания были удовлетворены. Не похоже, что это необходимо в ситуации, которую вы описали выше.

3 голосов
/ 12 апреля 2011

Статика - это зло.Не трогайте статику.

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

Также не проверяйте рядовые объекты, вам, вероятно, нужен класс там.

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

2 голосов
/ 12 апреля 2011

Проблема со статическими фабриками состоит в том, что вы не можете заменить фабрики (и иногда объекты, созданные фабриками) на фиктивные.- Это одна из причин, почему контейнеры IOC так полезны.

1 голос
/ 12 апреля 2011

Статические методы в основном убивают юнит-тестирование.

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

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

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

Misko Hevery имеет очень хороший пост на эту тему.

0 голосов
/ 12 апреля 2011

Статические методы сами по себе не являются злом. Посмотрите в JDK, сколько их там. Статические методы также должны быть проверены юнитами, так что если у вас есть какие-либо иди и проверить их.

Так что это не правда, что статические методы убивают юнит-тестирование.

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

И полный ACK для написания тестов в первую очередь - это также поможет вам лучше разрабатывать API, корректировать классы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...