LogoTRUONG PHAM
Home
Projects
Blogs
YouTube
Contact

Newsletter

Stay updated with technical artifacts and engineering insights.

LogoTRUONG PHAM

Building scalable software and sharing insights on technology & life.

Sitemap

  • Home
  • Projects
  • Blogs
  • YouTube
  • Contact

Connect

  • GitHub
  • LinkedIn
  • Email
  • YouTube

© 2024 TRUONG PHAM. © All rights reserved.

Privacy PolicyTerms of Service
Back
Contract Testing - When Integration Testing Becomes a Burden
Microservice Journey: Lessons & Trade-offs

Contract Testing - When Integration Testing Becomes a Burden

Service A mocks Service B the old way, while Service B has changed its API. How can a 2-person team confidently deploy without fear of breaking each other?

TP
Truong PhamSoftware Engineer
PublishedMarch 31, 2024
Stack
microservice ·testing ·quality-assurance

In a Monolith, the compiler will report an error if you call a function incorrectly. In Microservices, your 'compiler' is the network calls, and it only reports an error when the system has already crashed in Production.


The Problem: The Obsolescence of Mocks

In post 7, we talked about using Mocks for local development. But there's a classic scenario:

  1. Service A (Consumer) uses a Mock of Service B to run tests. Tests pass with flying colors.
  2. Service B (Provider) changes the returned JSON structure (e.g., changing the user_id field to id).
  3. Service A has no idea, still using the old Mock.
  4. You deploy both to Production and... BOOM! The system fails because Service A can't read the data from B anymore.

Traditional Integration Tests are often very slow and hard to maintain. We need a smarter solution.

1. What is Contract Testing?

Imagine a Contract as a formal agreement between two services.

  • Consumer (A): "I need you to return data in this format."
  • Provider (B): "I commit to always returning exactly that. If I want to change it, I must inform you."

Instead of running both services at the same time to test, we just need to check if each side complies with the "Contract" effectively "signed."

2. Pact - The Game-Changing Tool

We use Pact. The workflow is fascinating:

  1. Service A runs tests and generates a JSON file (the Contract).
  2. This file is pushed to a place called the Pact Broker.
  3. When Service B runs CI/CD, it downloads that file and verifies: "Does my actual data match what Service A expects?".
  4. If it doesn't match, Service B is not allowed to deploy.

3. Trade-off for Small Teams

The pain: Setting up a Pact Broker and writing Contract Tests takes extra effort. It requires a completely different mindset than writing normal Unit Tests.

The reward: Confidence. You can deploy Service B at 5 PM on a Friday knowing with 100% certainty that you aren't breaking Service A. For a small team, this confidence is invaluable because you don't have enough people to be on standby for 24/7 bug fixes.


Lessons Learned

  1. Consumer is the Power-holder: In Contract Testing, the service user (the Consumer) should be the one to set the requirements first.
  2. Minimize End-to-End (E2E) Testing: Don't try to write tests that stretch from the Frontend all the way to the final Database. They are very "flaky" and hard to debug. Contract Testing solves 80% of E2E problems much faster.
  3. Communication is Still Most Important: Tools are only aids. Always talk to your colleagues before making major changes to the API.

Conclusion

Contract Testing transforms "verbal" promises between developers into verifiable pieces of code. This is an important stepping stone for your small team to operate a system professionally and safely.

Series • Part 14 of 20

Microservice Journey: Lessons & Trade-offs

NextAI-Service Integration - Bringing LLM/RAG into Microservice Architecture
When the System Goes Silent - Lessons on Post-mortem and Blame-free Culture
09BFF (Backend for Frontend) - The Savior of UX10Idempotency - Why Every API Should Be 'Stubborn'?11Infra as Code (IaC) - Automate or Die in a Mountain of Config12The Pain Named Cloud Bill - Cost Optimization for 'Broke Teams'13When the System Goes Silent - Lessons on Post-mortem and Blame-free Culture14Contract Testing - When Integration Testing Becomes a BurdenReading15AI-Service Integration - Bringing LLM/RAG into Microservice Architecture16Feature Flags - Deploy and Release are No Longer One17Secret Management - Don't Let API Keys Wander Around18Macroservice - When We Decide to 'Merge' Services Back19The Maintenance Nightmare - When Microservice Systems Age
TP

Written by Truong Pham

Software Engineer passionate about building high-performance systems and meaningful experiences.

Read more articles