Ответ
Да, применял контрактное тестирование, в частности с помощью фреймворка Pact, для решения проблем интеграции в микросервисной архитектуре. Мы столкнулись с ситуацией, когда сервис-потребитель (consumer) и сервис-провайдер (provider) разрабатывались разными командами, и частые breaking changes в API провайдера ломали потребителя.
Как это работало на практике:
-
Со стороны потребителя (Consumer Tests): В наших автотестах для сервиса-потребителя мы использовали Pact для мокирования провайдера на основе ожидаемого контракта.
// Пример на JavaScript (Jest + Pact) const { Pact } = require('@pact-foundation/pact'); describe('User Service', () => { const provider = new Pact({ consumer: 'FrontendService', provider: 'UserApiService', }); beforeAll(() => provider.setup()); afterEach(() => provider.verify()); afterAll(() => provider.finalize()); it('should receive user data', async () => { // Определяем ожидаемое взаимодействие (контракт) await provider.addInteraction({ state: 'a user with id 123 exists', uponReceiving: 'a request for user data', withRequest: { method: 'GET', path: '/users/123', }, willRespondWith: { status: 200, headers: { 'Content-Type': 'application/json' }, body: { id: 123, name: 'John Doe', // Ожидаемая структура ответа }, }, }); // Выполняем тест против мока Pact const user = await fetchUser(123); expect(user.name).toBe('John Doe'); }); });После успешного прогона тестов Pact публиковал контракт (JSON-файл) в общий брокер (например, PactFlow).
-
Со стороны провайдера (Provider Verification): В пайплайне CI сервиса-провайдера запускалась задача верификации. Она забирала опубликованные контракты и прогоняла реальный API провайдера, проверяя, что он удовлетворяет всем ожиданиям потребителей.
# Команда для верификации провайдера pact-verifier --provider-base-url http://localhost:8080 --pact-broker-url https://our-broker.example.com --provider "UserApiService" --consumer-version-tags "prod"
Результат: Это позволило обнаруживать несовместимости на этапе Pull Request, а не в продакшене. Провайдер видел, что его изменения ломают конкретного потребителя, и мог либо скорректировать API, либо согласовать изменение с командой потребителя. Контрактное тестирование не заменило end-to-end тесты, но значительно снизило количество интеграционных сбоев.