API Automation from Zero to Confident · Lesson 6 of 6

Mocking & Contracts: Fast, Offline, Reliable Tests

If your tests hit a live API on every run, they get slow and flaky — failing when the wifi hiccups, not when your code is actually broken. There's a cleaner way.

By Shahriyar · Updated

The idea, in one line

Mocking swaps the real network call for a canned reply you control, so the test checks your logic instead of the internet's mood.

See it work

The responses library intercepts requests calls. Decorate a test with @responses.activate, register what a URL should return, and your code runs unchanged against the fake. This shines for the hard-to-trigger paths — force a 500 on demand and prove your error handling copes.

▸ try it
import requests, responses

def fetch_status(post_id):
    r = requests.get(f"https://api.example.com/posts/{post_id}",
                     timeout=5)
    return r.status_code

@responses.activate
def test_handles_server_error():
    # register a fake 500 for this URL
    responses.add(responses.GET,
                  "https://api.example.com/posts/1",
                  json={"error": "boom"}, status=500)

    assert fetch_status(1) == 500        # our code saw the 500
    assert len(responses.calls) == 1     # and made exactly one call

Read it top to bottom: you told responses to answer that URL with a 500, ran your function, then checked it saw the 500 and made exactly one call. No network involved — fast and repeatable.

Advanced — monkeypatch and contract testing

pytest's built-in monkeypatch fixture is the lower-level cousin: it swaps out any attribute or function for one test, handy when what you're faking isn't a plain HTTP call. One step up is contract testing (the Pact idea): the caller and the API agree on a shared contract — the exact shape of requests and replies — and each side tests against it on its own, catching breakages before the two ever meet.

Grounded in the responses library README (getsentry/responses) and pytest monkeypatch docs

All lessons in API Automation from Zero to Confident

  1. The HTTP Mental Model & Your First Postman Collection
  2. Recreate It in Code: requests + pytest with Shared State
  3. Trust the Shape: Schema Validation & Negative Testing
  4. Getting Past the Gate: API Keys, Bearer/JWT & OAuth2
  5. SQL for Testers: Prove the API Actually Wrote to the DB
  6. Mocking & Contracts: Fast, Offline, Reliable Tests