Тестирование интеграции клиент-сервер: макет или нет?

Я работаю над проектом с двумя приложениями: Android-приложение (клиент) и сервис отдыха (сервер). Мое приложение для Android использует мой сервис для отдыха.

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

Теперь эта техника работает очень хорошо. Мне это нравится. Я могу использовать различные тестовые среды и среды непрерывной интеграции. Но есть одна слабость. В обоих (клиентских и серверных) случаях я указываю один и тот же api. Я предполагаю, что, например,

GET /foo-list.json

вернет HTTP 200 с помощью json

[{
    id: 1,
    name: foo1,
}, {
    id: 2,
    name: foo2
}]

Итак, повторяю. Если я изменю формат ответа, мои тесты клиента не будут терпеть неудачу.

Мой вопрос касается хороших практик при тестировании такого сценария. Как сделать настоящие интеграционные тесты, не жертвуя гибкостью независимых тестов. Должен ли я тестировать клиента с издеваемым сервером или с реальным экземпляром моего сервиса отдыха?

Поделитесь своим опытом.

Ответ 1

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

Вы спрашиваете:

"Как сделать настоящие интеграционные тесты, не жертвуя гибкостью независимых тестов"

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

также:

"Должен ли я тестировать клиента с посмеянным сервером или с реальным экземпляром моего сервиса отдыха?"

В дополнение к тестированию на единицу и интеграцию вы также должны выполнить тестирование интеграции клиент-сервер; Для этого я использую автоматическое приемочное тестирование. Используя тестовую структуру, такую ​​как Cucumber (также проверьте calaba.sh, который написан специально для тестирования мобильных приложений), вы можете написать тесты, которые будут проверять специфические функции и сценарии, которые будут взаимодействовать как с клиентом (вашим Android-приложением), так и с сервером (ваш сервис RESTful). Эти тесты интеграции клиент-сервер будут запускаться и останавливать конкретные экземпляры клиента и сервера.

Ответ 2

Mocks для модульного тестирования. Ваше описание тестов с помощью mocks точно описывает это. Вы проверяете клиент и сервер как отдельные блоки.

Интеграционные тесты тестирования, если блоки работают хорошо. Так как интерфейс является интерфейсом REST, насмешка не имеет смысла, вам нужно проверить реальность по HTTP.

См. также В чем разница между интеграционными и модульными тестами?

Ответ 3

Если ваша служба основана на Java, я настоятельно рекомендую изучить структуру Spock, чтобы высмеивать любые вызовы, которые могут возникать у клиента. Поскольку Spock - это просто расширение jUnit, вы также можете использовать его для Android (хотя, честно говоря, я никогда не делал разработку Android).

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

Однако в ваших обычных коммитов я предлагаю модульное тестирование, которое отбрасывает все, кроме тестируемого класса. Спок делает это довольно легко, и поскольку он построен поверх jUnit, все это берет банку.

Ответ 4

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

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

Я бы только создал макет службы, если служба была внешней службой, над которой я не контролировал!