Контрактные тесты: Pact, проверка proto и GraphQL-схем

↑ 5.7 Тестирование интеграций · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

Как командам микросервисов не ломать друг друга при изменениях API.

Объяснение

Контрактный тест проверяет, что обе стороны интеграции согласны с форматом сообщений, не поднимая всю систему.

Consumer-driven contracts (Pact):

  1. Потребитель описывает ожидаемые запросы и ответы, тест на моке провайдера формирует файл-контракт (pact).
  2. Контракт публикуется в Pact Broker.
  3. Поставщик в CI проигрывает контракты против реальной реализации.
  4. can-i-deploy блокирует релиз, ломающий контракт потребителей.
var pact = Pact.V4("orders-ui", "orders-api", new PactConfig());
var http = pact.WithHttpInteractions();
http.UponReceiving("get order").Given("order 42 exists")
    .WithRequest(HttpMethod.Get, "/orders/42")
    .WillRespond().WithStatus(200).WithJsonBody(new { id = 42, status = Match.Type("paid") });
 
await http.VerifyAsync(async ctx => { var o = await new OrdersClient(ctx.MockServerUri).GetAsync(42); Assert.Equal("paid", o.Status); });

Для схем без Pact:

ТехнологияПроверка
OpenAPIлинтер (Spectral), сравнение схем (oasdiff breaking)
gRPC/protobuf breaking против основной ветки
GraphQLgraphql-inspector diff, проверка на реальных запросах клиентов
События (Kafka)Schema Registry с режимом совместимости

Нюансы и подводные камни

  • Контракт описывает то, что реально использует потребитель, а не всю схему.
  • Состояния провайдера («order 42 exists») нужно уметь подготавливать в тесте провайдера.
  • Проверка схем ловит структурные поломки, но не смысловые (изменение семантики поля).
  • Без culture «сначала контракт» тесты становятся формальностью: включайте проверки в CI как блокирующие.

Практика

  1. Настройте Pact между фронтендом и API (или двумя сервисами) с Pact Broker.
  2. Добавьте buf breaking и oasdiff в CI.
  3. Смоделируйте ломающее изменение и убедитесь, что CI его блокирует.

Вопросы с ответами

Связанные темы