Code of the Day
AdvancedTesting Automation Scripts

Mocking HTTP in practice

Use the responses library to intercept requests calls in tests — assert the right URL was called, return fake JSON, and test your error-handling code with a simulated 500.

WorkflowAdvanced10 min read
Recommended first
By the end of this lesson you will be able to:
  • Use responses.activate and responses.add to mock a GET request returning JSON
  • Assert that exactly the right URL was called and with the right parameters
  • Test error-handling code by registering a 500 response

The previous lesson explained why responses is the right tool for unit-testing HTTP-dependent pipeline code. Here you will build and test a small fetch_records function that has both a happy path and an error path.

Because the responses library is not available in the in-browser runtime, the demo below simulates its core behaviour using unittest.mock. The API and assertions are identical to what you would write with the real library — swap the import and decorator to use it in your own test files.

Python — editable, runs in your browser

Using the real responses library

In your actual test file, replace the mock with responses:

import responses
import requests

def fetch_records(url: str) -> list:
    resp = requests.get(url, timeout=10)
    resp.raise_for_status()
    return resp.json()

@responses.activate
def test_fetch_records_happy_path():
    responses.add(
        responses.GET,
        "https://api.example.com/records",
        json=[{"id": 1, "name": "alpha"}, {"id": 2, "name": "beta"}],
        status=200,
    )
    result = fetch_records("https://api.example.com/records")
    assert len(result) == 2
    assert len(responses.calls) == 1
    assert responses.calls[0].request.url == "https://api.example.com/records"

@responses.activate
def test_fetch_records_500_raises():
    responses.add(
        responses.GET,
        "https://api.example.com/records",
        status=500,
    )
    try:
        fetch_records("https://api.example.com/records")
        assert False, "Expected an exception"
    except Exception as exc:
        assert "500" in str(exc)

By default, responses raises ConnectionError for any URL that is not registered. This is a feature: it prevents your code from silently hitting live endpoints during a test run. If you need to allow passthrough for specific URLs, use responses.add_passthrough(pattern).

Asserting request details

responses.calls gives you the full request history. You can assert headers and request body:

assert responses.calls[0].request.headers["Authorization"] == "Bearer test-token"
assert json.loads(responses.calls[0].request.body) == {"filter": "active"}

This matters for testing authentication flows: verify that your code adds the correct Authorization header rather than trusting that it "probably" does.

Where to go next

Next: lab — test suite — combine filesystem mocking, HTTP mocking, and error path testing into a complete test suite covering every function in a pipeline script.

Finished reading? Mark it complete to track your progress.

On this page