REST API Contract Testing and Mocking

Frontend and backend teams often build at the same time. The frontend waits for endpoints, and the backend waits for feedback. One team changes a field name, and the other team's app breaks in production. Contracts and mocks fix both problems by agreeing on the API shape first.

The Blueprint Picture

Builders and electricians work from one blueprint. The electrician installs outlets where the plan says, even before the walls exist. Inspectors compare the finished house against the same plan. An API contract plays that blueprint role for software teams.

What a Contract Contains

An OpenAPI file lists the paths, methods, request fields, response fields, types, and status codes. Both teams treat it as the source of truth.

paths:
  /books/{id}:
    get:
      responses:
        "200":
          description: One book
          content:
            application/json:
              schema:
                type: object
                required: [id, title, price]
                properties:
                  id: { type: string }
                  title: { type: string }
                  price: { type: integer }

Mock Servers

A mock server reads the contract and answers requests with sample data. Frontend developers start building screens on day one, with no backend ready.

Frontend App ──→ Mock Server (built from contract) ──→ sample JSON
Later:
Frontend App ──→ Real Backend                      ──→ real JSON

Mocks also simulate rare situations that are hard to trigger on a real server, such as a 503 error, a slow response, or an empty list.

Mock Response Examples

ScenarioMock Behavior
Happy path200 with a complete book
Not found404 with the standard error body
Server failure503 to test retry logic
Slow networkResponse delayed by 5 seconds

Contract Testing

Contract tests prove that the real API still matches the agreed shape. The test calls an endpoint and compares the response against the schema. Any extra, missing, or mistyped field fails the test.

CI pipeline
   │
   ├─ start the backend
   ├─ call each endpoint with sample data
   ├─ validate responses against the OpenAPI schema
   └─ fail the build on any mismatch

Teams run these tests on every code change, so a broken contract never reaches users.

Consumer-Driven Contracts

In this approach, each client team records exactly which fields and behaviors it relies on. The backend team runs those recorded expectations as tests. Pact is a popular tool for this style.

Frontend team ── writes expectations ──→ contract file
Backend CI    ── replays expectations against the real API
     pass: safe to release       fail: tell the frontend team

The backend learns about breaking changes before release. Fields that no client uses can leave safely, and fields that clients depend on stay protected.

Spec First or Code First

ApproachProcessStrength
Spec firstWrite the contract, then build both sidesTeams work in parallel
Code firstWrite code, then generate the contractDocumentation always matches code

Both styles work when automated checks keep the file and the code in sync.

Catching Breaking Changes Automatically

Diff tools compare two versions of a contract and report removed fields, changed types, and new required inputs. Run the diff in code review. A reviewer sees at a glance whether a change will break clients.

Good Practices

  • Store the contract in version control beside the code.
  • Review contract changes like code changes.
  • Include error responses in the contract, not just success cases.
  • Keep mock data realistic, with believable names, dates, and amounts.

Common Mistakes

Outdated Contracts

A contract that nobody updates misleads everyone. Automated checks keep it honest.

Mocks That Hide Problems

Mocks that always succeed give false confidence. Include failures and edge cases.

Testing Only Success Paths

Clients meet errors in production. Test 4xx and 5xx responses against the contract.