Зачем мокировать API?
Мокирование API создаёт имитации реальных API, возвращающие предопределённые ответы. Это необходимо в современной разработке:
Типичные сценарии для мокирования
- Недоступность стороннего API — песочница платёжного провайдера упала, но нужно тестировать оплату
- API в разработке — бэкенд-команда ещё не закончила endpoint
- Снижение затрат — вызов платных API (Google Maps, OpenAI) тысячи раз при тестировании дорог
- Детерминированное тестирование — реальные API могут возвращать разные данные; моки — стабильные
- Имитация граничных случаев — сложно вызвать 500 от реального API; моки имитируют любой ответ
- Тестирование производительности — имитация медленных ответов, таймаутов, сетевых ошибок
- Офлайн-разработка — разработчики могут работать без интернета
Stubs vs. Mocks vs. Fakes
| Термин | Определение | Пример |
|---|---|---|
| Stub | Возвращает предопределённые ответы | Возвращает {id: 1, name: "Alice"} на любой GET /users/1 |
| Mock | Stub + проверяет ожидания | То же, но проверяет, что запрос был сделан ровно один раз |
| Fake | Упрощённая рабочая реализация | In-memory БД вместо реальной PostgreSQL |
Введение в WireMock
WireMock — самый популярный инструмент мокирования API в экосистеме Java, но работает с любым языком через HTTP API или standalone-сервер.
Запуск WireMock
Standalone:
java -jar wiremock-standalone-3.3.1.jar --port 8080
Docker:
docker run -d -p 8080:8080 wiremock/wiremock:latest
Создание первого Stub
{
"request": {
"method": "GET",
"url": "/api/users/1"
},
"response": {
"status": 200,
"headers": {"Content-Type": "application/json"},
"jsonBody": {
"id": 1,
"name": "Alice Johnson",
"email": "alice@example.com"
}
}
}
Через HTTP API:
curl -X POST http://localhost:8080/__admin/mappings -d '{
"request": {"method": "GET", "urlPattern": "/api/users/[0-9]+"},
"response": {"status": 200, "jsonBody": {"id": 1, "name": "Alice"}}
}'
Request Matching
URL Matching
{"url": "/api/users/1"} // Точное совпадение
{"urlPattern": "/api/users/[0-9]+"} // Regex
{"urlPathPattern": "/api/users/.*"} // Паттерн пути
Matching заголовков и тела
WireMock поддерживает сложное сопоставление заголовков, query-параметров и тела через JSON paths и regex-паттерны.
Продвинутые возможности WireMock
Имитация задержек
{
"request": {"method": "GET", "url": "/api/slow"},
"response": {
"status": 200,
"fixedDelayMilliseconds": 3000,
"jsonBody": {"data": "задержанный ответ"}
}
}
Имитация ошибок
{
"request": {"method": "GET", "url": "/api/error"},
"response": {"status": 500, "jsonBody": {"error": "Internal Server Error"}}
}
{
"request": {"method": "GET", "url": "/api/timeout"},
"response": {"fault": "CONNECTION_RESET_BY_PEER"}
}
Stateful-поведение (сценарии)
Разные ответы в зависимости от состояния:
[
{
"scenarioName": "Жизненный цикл пользователя",
"requiredScenarioState": "Started",
"newScenarioState": "Пользователь создан",
"request": {"method": "POST", "url": "/api/users"},
"response": {"status": 201, "jsonBody": {"id": 1, "name": "Alice"}}
},
{
"scenarioName": "Жизненный цикл пользователя",
"requiredScenarioState": "Пользователь создан",
"request": {"method": "GET", "url": "/api/users/1"},
"response": {"status": 200, "jsonBody": {"id": 1, "name": "Alice"}}
}
]
Верификация запросов
curl http://localhost:8080/__admin/requests/count -d '{
"method": "POST", "url": "/api/users"
}'
# Ответ: {"count": 1}
Response Templating
Динамические ответы на основе данных запроса с плейсхолдерами.
Стратегии мокирования
Паттерн виртуализации сервисов
Для микросервисов мокируйте внешние зависимости, сохраняя реальные внутренние компоненты.
Мок в CI/CD
services:
wiremock:
image: wiremock/wiremock:latest
ports: ["8080:8080"]
volumes: ["./tests/mocks:/home/wiremock"]
Альтернативы WireMock
| Инструмент | Язык | Лучше всего для |
|---|---|---|
| WireMock | Java/Любой | Enterprise, сложный matching |
| json-server | Node.js | Быстрый мок из JSON-файла |
| Prism | Любой | Авто-мок из OpenAPI-спецификации |
| MSW | JavaScript | Перехват запросов в браузере/Node.js |
| Mountebank | Любой | Мульти-протокольный (HTTP, TCP, SMTP) |
Практическое упражнение
- Настройте WireMock: Запустите standalone или через Docker. Создайте stub-ы для GET, POST и DELETE.
- Request matching: Создайте stub-ы, отвечающие по-разному в зависимости от query-параметров, заголовков и тела.
- Имитируйте сбои: Создайте stub-ы для ошибок 500, таймаутов и сбросов соединения.
- Верифицируйте запросы: Используйте API верификации, чтобы подтвердить, что клиент сделал ожидаемые запросы.
- Stateful-мок: Создайте сценарий, где POST создаёт ресурс, а последующий GET его возвращает.
Ключевые выводы
- Мокирование API имитирует реальное поведение для тестирования, когда API недоступен или непредсказуем
- WireMock — отраслевой стандарт: поддерживает request matching, templating, задержки, сбои и stateful-сценарии
- Stub-ы возвращают предопределённые ответы; mock-и добавляют верификацию ожидаемых запросов
- Используйте мокирование для сторонних API, API в разработке, имитации граничных случаев и CI/CD
- Response templating и stateful-сценарии обеспечивают реалистичное поведение моков