Я пытаюсь протестировать класс, который вызывает некоторые веб-сервисы Hadoop. Код в значительной степени имеет вид:
method() {
...use Jersey client to create WebResource...
...make request...
...do something with response...
}
например, есть метод создания каталога, метод создания папки и т. д.
Учитывая, что код имеет дело с внешним веб-сервисом, который я не могу контролировать, как я могу выполнить это модульное тестирование? Я мог бы попытаться издеваться над клиентом / ответами веб-службы, но это нарушает принцип, который я часто видел в последнее время: «Не издевайтесь над объектами, которые вам не принадлежат». Я мог бы настроить фиктивную реализацию веб-службы - это все еще будет «модульный тест» или это будет интеграционный тест? Разве нельзя провести модульное тестирование на этом низком уровне - как бы это сделал практикующий врач TDD?
unit-testing
tdd
web-services
integration-tests
Крис Купер
источник
источник
Ответы:
На мой взгляд, вы должны высмеивать вызовы веб-службы, если это модульный тест, а не интеграционный тест.
Ваш модульный тест не должен проверять, работает ли внешний веб-сервис или правильна ваша интеграция с ним. Не слишком догматично относясь к TDD, обратите внимание, что побочным эффектом превращения вашего модульного теста в интеграционный тест является то, что он может работать медленнее, и вам нужны быстрые модульные тесты.
Кроме того, если веб-служба временно недоступна или работает неправильно, это может привести к сбою модульного теста? Это не кажется правильным. Ваш модульный тест должен завершиться неудачей только по одной причине: если в коде этого «модуля» есть ошибка.
Единственная часть кода, которая здесь уместна, это
...do something with response...
. Дразнить остальных.источник
Я не согласен с «не издевайтесь над объектами, которые вам не принадлежат», когда вы проводите модульное тестирование.
Ложная цель существования заключается в том, что появятся модули, библиотеки, классы, которыми мы не будем владеть.
Мое предложение для вашего сценария - издеваться над вызовом веб-службы.
Настройте макет таким образом, чтобы он возвращал данные обратно в ваш модуль.
Убедитесь, что вы охватили весь сценарий, например, когда возвращаемые данные равны нулю, когда возвращенные данные верны и т. Д.
А для кода, которым вы владеете, ваша ответственность как разработчика заключается в том, чтобы гарантировать, что код, который вы создаете, работает должным образом во всех сценариях.
источник
Я бы использовал что-то вроде EasyMock для этого теста. Фреймворки Mocking - это идеальный способ удаления внешних зависимостей класса, который дает вам полный контроль над результатами внешних зависимостей во время тестов. Чтобы немного расширить ваш пример:
Первое, что вам нужно сделать, это извлечь логику в вашем классе, где вы используете Jersey, чтобы получить WebResource и вызвать веб-сервис в отдельный класс. Создание интерфейса для этого класса позволит вам создать макет, которому вы затем сможете диктовать поведение.
После создания этого интерфейса вы можете создать макет с помощью EasyMock, который вернет указанный объект в соответствии с вашим тестовым примером. Приведенный выше пример является упрощением того, как структурировать базовый макетированный тест и как будет работать ваш интерфейс.
Для получения дополнительной информации о фреймворках, пожалуйста, смотрите этот вопрос . Кроме того, в этом примере предполагается использование Java, но среды разработки доступны на всех языках, и, хотя они реализованы по-разному, в целом они будут работать одинаково
источник
В этом случае допустимы насмешки, но они вам не нужны. Вместо модульного тестирования
method()
, вместо модульного тестирования только часть, которая обрабатывает ответ.Извлеките функцию, которая принимает
ResponseData
(любого подходящего типа) и затем выполняет действие.Вместо насмешек, теперь вы просто создаете объект ResponseData и передаете его.
Вы можете оставить вызов службы на полное интеграционное тестирование, которое охватит
method()
всегоисточник
Что я сделал, и это работает:
3.1 Сначала все веб-сервисы тестируются. С каждой машины, даже машины разработчика. Это настоящие веб-сервисы, но работающие в среде разработки. Это означает, что веб-сервисы никогда не могут выйти из строя или ответить ошибочными значениями, потому что в противном случае каждый разработчик жалуется, что не может скомпилировать.
3.2 Затем запускаются все модульные тесты, внутренние для приложения. Это означает, что все веб-сервисы проверяются и тестируются, выполняя те же тесты, что и 3.1 (и они должны проходить тоже, в противном случае ложные проверки неверны), и вызываются реальным приложением, как если бы они действительно использовались. Если макеты ошибочны, вы можете запустить тест в 3.1 и записать эти значения (запрос, ответ) в HashMap.
3.3 Затем запускаются те же тесты, что и в 3.2, но на этот раз с реальными веб-сервисами, работающими в среде разработки.
После того, как все это будет выполнено, для реальной производственной среды вам просто нужно предоставить реальный адрес для каждого веб-сервиса. Надеюсь, это не потребует слишком больших изменений в конфигурации.
источник