2 min read

Microservice Contract Testing Guide

How to reduce communication failures after deployment by verifying the provider/consumer contract at the CI stage

Microservice Contract Testing Guide thumbnail

Introduction

The most common cause of failure in microservices is interface mismatch, not network. Even if the other service slightly changes the response format, it immediately becomes an obstacle for the consumer. This article introduces how to establish consumer-led contract testing in practice.

마이크로서비스 Contract Testing 가이드 커버
Wikimedia Commons 기반 무료 이미지

Problem definition

It is difficult to quickly catch contract regression between services through integration testing alone.

  • Even if the document and actual response are different, it is not detected before distribution.
  • There is no backward compatibility policy, so errors occur when adding/deleting fields.
  • Dependency on deployment order between service teams increases, causing release bottlenecks.

The key to contract testing is shifting responsibility. The most effective structure is to specify the contract expected by the consumer and have the provider verify it.

Key concepts

perspectiveDesign criteriaVerification points
Write a contractConsumer Expectations SpecificationTest Case Fidelity
Provider VerificationVerification of pact in Provider CIPre-deployment failure detection rate
version policyPrioritize backwards compatibilityNumber of breaking changes
CollaborationContract Change Review ProcessReduce conflict between teams

Contract testing is not about adding QA, but improving the distribution system. Reduces dependencies between teams and enables independent deployment.

Code Example 1: Consumer Contract Definition

import { PactV3, MatchersV3 } from "@pact-foundation/pact";

const provider = new PactV3({ consumer: "web-app", provider: "user-service" });

provider
  .given("user 1001 exists")
  .uponReceiving("a request for user profile")
  .withRequest({ method: "GET", path: "/users/1001" })
  .willRespondWith({
    status: 200,
    body: {
      id: MatchersV3.string("1001"),
      name: MatchersV3.string("moriya"),
      role: MatchersV3.string("admin"),
    },
  });

Code Example 2: Provider Verification Pipeline

#!/usr/bin/env bash
set -euo pipefail

pact-broker can-i-deploy \
  --pacticipant user-service \
  --version "$GIT_SHA" \
  --to-environment production

npm run test:contract:provider

Architecture flow

Mermaid diagram rendering...

Tradeoffs

  • Introducing contract testing has initial setup costs, but significantly reduces integration obstacles.
  • The consumer-led model is clear, but requires an additional consensus process between teams.
  • Strengthening the verification gate may reduce deployment speed, but increase release stability.

Cleanup

If you want to deploy microservices independently, contract testing is essential. By codifying consumer expectations and validating them in provider CI, interface regressions can be prevented before deployment.

Image source

  • Cover: source link
  • License: CC BY-SA 4.0 / Author: Zeljko.filipin
  • Note: After downloading the free license image from Wikimedia Commons, it was optimized to JPG at 1600px.

Comments