Facade (Фасад)
Проблема
Подготовка тестовых данных через API — распространённая задача. Чтобы создать пользователя с заказом, тест вынужден работать напрямую с несколькими API-клиентами: UserApi, OrderApi, PaymentApi, InventoryApi. Каждый вызов — своя сигнатура, свои исключения, своя последовательность. Тестовый метод превращается в набор низкоуровневых HTTP-вызовов, не связанных с тестируемым сценарием.
Facade предоставляет упрощённый интерфейс к сложной подсистеме. TestDataFacade скрывает за одним методом всю цепочку API-вызовов. Тест вызывает facade.createUserWithOrder(...) и получает готовые данные — не зная, сколько HTTP-запросов было сделано «под капотом».
Структура модуля
facade/
├── build.gradle
└── src/
├── main/
│ └── java/
│ └── dev/shipovalov/facade/
│ ├── TestDataFacade.java # Фасад: упрощённый API для подготовки данных
│ ├── api/
│ │ ├── UserApi.java # Клиент API управления пользователями
│ │ └── OrderApi.java # Клиент API управления заказами
│ └── model/
│ ├── User.java # Модель пользователя
│ └── Order.java # Модель заказа
└── test/
└── java/
└── dev/shipovalov/facade/
└── FacadePatternTest.java # Тест, использующий только фасад
Ключевые классы
| Класс | Назначение |
|---|---|
UserApi |
Низкоуровневые операции: создать, получить, удалить пользователя через HTTP |
OrderApi |
Низкоуровневые операции: создать заказ, добавить позиции, подтвердить |
TestDataFacade |
Оркестрирует вызовы UserApi и OrderApi, предоставляет методы уровня бизнес-сценария |
FacadePatternTest |
Тест работает только через фасад, не зависит от деталей API |
Сравнение подходов
// Без фасада — тест знает о деталях каждого API
UserApi userApi = new UserApi(baseUrl, token);
OrderApi orderApi = new OrderApi(baseUrl, token);
User user = userApi.createUser(new CreateUserRequest("john", "john@example.com", "USER"));
userApi.activate(user.getId());
Order order = orderApi.createOrder(new CreateOrderRequest(user.getId()));
orderApi.addItem(order.getId(), "PRODUCT-42", 2);
orderApi.confirm(order.getId());
// И только теперь можно тестировать...
// С фасадом — намерение выражено одной строкой
TestDataFacade facade = new TestDataFacade(baseUrl, token);
TestContext ctx = facade.createActiveUserWithConfirmedOrder("john", "PRODUCT-42", 2);
// ctx.getUser(), ctx.getOrder() — всё готово
Запуск тестов
./gradlew :facade:test
Отчёт о результатах: facade/build/reports/tests/test/index.html