Contract Testing
The backend renamed a field in the response, and our frontend crashed on deploy. How can we catch this automatically on commit?
The backend renamed a field in the response, and our frontend crashed on deploy. How can we catch this automatically on commit?
api.service.local/v1/users/42const avatar = user.avatar_url const name = user.nickname
GET /v1/users/42 → 200
{
"avatar_url": "string",
"nickname": "string"
}↳The contract records only fields the page truly reads; the backend may return more.
Before: both sides rely on an informal agreement: The profile page reads avatar_url, while a backend refactor renames it to avatar. Backend unit tests can still pass because they do not know which response fields the frontend depends on. The breakage may surface only during integration or after release.
Add the contract and return provider feedback: A consumer test records the minimum agreement for a real request: a successful status and the required id, avatar_url, and nickname fields with their expected types. Provider verification replays the scenario in CI; if avatar_url is missing, it should name the field and block the incompatible change. Pact is one common implementation tool, not a synonym for contract testing.
Prove the guard works: For acceptance, intentionally rename avatar_url and confirm the check fails. Restore the old field or add a compatibility mapping and confirm it passes. This proves the test can catch this breakage rather than merely adding another always-green script.
Our frontend depends on GET /v1/users/:id returning id, avatar_url, and nickname. Add a consumer contract from the fields the frontend actually reads, then verify the backend response in CI. Rename avatar_url to avatar and confirm the PR reports the missing field and cannot merge; restore compatibility and confirm the check passes.