pytest-responses
pytest-responses is a Pytest plugin that seamlessly integrates the `responses` library into your test suite. It automatically activates `responses`, a utility for mocking the Python `requests` library, across your tests, preventing actual HTTP requests. This helps create fast, reliable, and isolated unit and integration tests. The current version is 0.5.1, and its release cadence is irregular, with updates driven by bug fixes and compatibility needs.
Common errors
-
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionRefusedError(111, 'Connection refused'))cause An HTTP request was made during a test where `responses` was active, but no matching mock was registered for the requested URL and HTTP method.fixEither add a corresponding `responses.add()` call for the exact URL and method being requested in your test, or, if an actual external network call is intended for that specific test, use `@pytest.mark.withoutresponses`. -
AssertionError: Expected 1 requests, 0 have been made.
cause The code under test made an HTTP request, but the URL, HTTP method, or other parameters of the request did not exactly match any of the registered mocks in `responses.add()`.fixCarefully inspect the actual HTTP request made by your code (e.g., by debugging or logging) and ensure that the `responses.add()` call precisely matches the URL (including query parameters if `match_querystring=True`), HTTP method (GET, POST, etc.), and any headers or body content that might be used for matching. -
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: ...
cause Your test code expected a successful response (e.g., 200 OK), but the mock was configured to return a 4xx or 5xx status code, or no mock matched and the default behavior is to raise a connection error, but `responses` was in passthrough mode, causing a real 404.fixVerify that your `responses.add()` call specifies the expected `status=200` (or another success code). If you are intentionally testing an error scenario, ensure your test asserts for the `requests.exceptions.HTTPError` as shown in the quickstart example.
Warnings
- gotcha By default, `pytest-responses` intercepts ALL HTTP requests when `responses` is activated, preventing actual network calls. If you need to make a real external HTTP request in a specific test, `responses` must be explicitly disabled for that test.
- gotcha The underlying `responses` library, which `pytest-responses` integrates, has specific Python and `requests` library version requirements.
- gotcha Using `responses.add()` calls within a custom pytest fixture can sometimes lead to unexpected 'mock not used' errors or test isolation issues, especially if `responses.assert_all_requests_are_fired` is enabled.
- deprecated Version 0.5.1 fixed an internal usage of the deprecated `LooseVersion` class.
Install
-
pip install pytest-responses
Imports
- responses.activate
from responses import RequestsMock # Direct import of RequestsMock is less common for pytest-responses usage
import responses @responses.activate def test_something(): ...
Quickstart
import pytest
import requests
import responses
def fetch_user_data(user_id):
response = requests.get(f"https://api.example.com/users/{user_id}")
response.raise_for_status()
return response.json()
def test_fetch_user_data_success(responses):
# Add a mock response for the specific URL and method
responses.add(
responses.GET,
'https://api.example.com/users/123',
json={'id': 123, 'name': 'Test User'},
status=200
)
# Call the function that makes the HTTP request
data = fetch_user_data(123)
# Assert the returned data and that the mock was called
assert data == {'id': 123, 'name': 'Test User'}
assert len(responses.calls) == 1
assert responses.calls[0].request.url == 'https://api.example.com/users/123'
def test_fetch_user_data_not_found(responses):
responses.add(
responses.GET,
'https://api.example.com/users/404',
status=404
)
with pytest.raises(requests.exceptions.HTTPError) as exc_info:
fetch_user_data(404)
assert exc_info.value.response.status_code == 404
assert len(responses.calls) == 1