mock-response-delay
Simulate a slow server, and the client timeout it causes, in HTTP mocks.
responses and respx answer requests instantly, so a test of how code handles a slow server, or a timeout, has nothing to exercise. This package wraps a mock’s callback so that it answers as a server which takes a given number of seconds would. A request whose read timeout is shorter than the delay waits for the timeout and then raises the same exception which the client library raises against a real slow server. Any other request gets the response after waiting for the delay.
The waiting is done by a function which you can replace, so a test can record the waits, or advance a fake clock, instead of really sleeping.
Installation
Install the extra for the client library which the code under test uses:
pip install 'mock-response-delay[requests]'
pip install 'mock-response-delay[httpx]'
pip install 'mock-response-delay[httpx2]'
This requires Python 3.12+.
Usage
requests with responses
Wrap a callback before giving it to responses. A request with a read timeout shorter than the delay raises requests.exceptions.Timeout:
"""Time out against a slow server."""
import pytest
import requests
import responses
from requests import PreparedRequest
from mock_response_delay.for_requests import delayed_responses_callback
def slow_callback(request: PreparedRequest) -> tuple[int, dict[str, str], str]:
"""Answer any request."""
del request
return (200, {}, "Hello")
waits: list[float] = []
with responses.RequestsMock() as mock:
mock.add_callback(
method="GET",
url="https://example.com/",
callback=delayed_responses_callback(
callback=slow_callback,
delay_seconds=5.0,
sleep_fn=waits.append,
),
)
with pytest.raises(expected_exception=requests.exceptions.Timeout):
requests.get(url="https://example.com/", timeout=1.0)
response = requests.get(url="https://example.com/", timeout=10.0)
assert response.text == "Hello"
assert waits == [1.0, 5.0]
requests accepts the timeout as one number, or as a (connect, read) tuple. A slow server only affects the read leg, so only the read timeout is compared with the delay.
httpx with respx or httpx.MockTransport
Wrap a handler before giving it to httpx.MockTransport, or to respx as a side effect. A request with a read timeout shorter than the delay raises httpx.ReadTimeout:
"""Time out against a slow server."""
import httpx
import pytest
from mock_response_delay.for_httpx import delayed_httpx_handler
def slow_handler(request: httpx.Request) -> httpx.Response:
"""Answer any request."""
del request
return httpx.Response(status_code=200, text="Hello")
waits: list[float] = []
transport = httpx.MockTransport(
handler=delayed_httpx_handler(
handler=slow_handler,
delay_seconds=5.0,
sleep_fn=waits.append,
),
)
with httpx.Client(transport=transport) as client:
with pytest.raises(expected_exception=httpx.ReadTimeout):
client.get(url="https://example.com/", timeout=1.0)
response = client.get(url="https://example.com/", timeout=10.0)
assert response.text == "Hello"
assert waits == [1.0, 5.0]
httpx2
httpx2 has its own request, response and exception classes, so it has its own module, which works in the same way with httpx2.MockTransport:
"""Time out against a slow server."""
import httpx2
import pytest
from mock_response_delay.for_httpx2 import delayed_httpx2_handler
def slow_handler(request: httpx2.Request) -> httpx2.Response:
"""Answer any request."""
del request
return httpx2.Response(status_code=200, text="Hello")
waits: list[float] = []
transport = httpx2.MockTransport(
handler=delayed_httpx2_handler(
handler=slow_handler,
delay_seconds=5.0,
sleep_fn=waits.append,
),
)
with httpx2.Client(transport=transport) as client:
with pytest.raises(expected_exception=httpx2.ReadTimeout):
client.get(url="https://example.com/", timeout=1.0)
response = client.get(url="https://example.com/", timeout=10.0)
assert response.text == "Hello"
assert waits == [1.0, 5.0]
Controlling the clock
sleep_fn defaults to time.sleep, so by default the delay is real. The examples above record the waits instead, which keeps the test instant. Something which advances a fake clock, such as a freezegun tick, works the same way.
Full documentation
See the full documentation.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mock_response_delay-2026.9.7.tar.gz.
File metadata
- Download URL: mock_response_delay-2026.9.7.tar.gz
- Upload date:
- Size: 152.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06f74384b7eed3daf74f83a2a4821bdf699accb286d940e982326b8e6228fe64
|
|
| MD5 |
d5a422356ba96183be660e450edae5be
|
|
| BLAKE2b-256 |
dae4994f1f6b3efca29fac956c1f40ccb0973f093ee096fd19ca9841d62fe347
|
Provenance
The following attestation bundles were made for mock_response_delay-2026.9.7.tar.gz:
Publisher:
release.yml on adamtheturtle/mock-response-delay
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mock_response_delay-2026.9.7.tar.gz -
Subject digest:
06f74384b7eed3daf74f83a2a4821bdf699accb286d940e982326b8e6228fe64 - Sigstore transparency entry: 2752399321
- Sigstore integration time:
-
Permalink:
adamtheturtle/mock-response-delay@1ff90a3ea68ced5475519f754abc09cdd5431ff1 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adamtheturtle
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1ff90a3ea68ced5475519f754abc09cdd5431ff1 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file mock_response_delay-2026.9.7-py3-none-any.whl.
File metadata
- Download URL: mock_response_delay-2026.9.7-py3-none-any.whl
- Upload date:
- Size: 10.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
841a414b6a433afb672d12df6e3a05a37f64f94d6742390fe4aacc5dd99e10a6
|
|
| MD5 |
a7f32495630a8971db96eec082627712
|
|
| BLAKE2b-256 |
e17bc9e0c7f3bc4175c1be6e1ce24194b42f4723b9d176ff04b5425dc2355dfb
|
Provenance
The following attestation bundles were made for mock_response_delay-2026.9.7-py3-none-any.whl:
Publisher:
release.yml on adamtheturtle/mock-response-delay
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mock_response_delay-2026.9.7-py3-none-any.whl -
Subject digest:
841a414b6a433afb672d12df6e3a05a37f64f94d6742390fe4aacc5dd99e10a6 - Sigstore transparency entry: 2752399375
- Sigstore integration time:
-
Permalink:
adamtheturtle/mock-response-delay@1ff90a3ea68ced5475519f754abc09cdd5431ff1 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adamtheturtle
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1ff90a3ea68ced5475519f754abc09cdd5431ff1 -
Trigger Event:
workflow_dispatch
-
Statement type: