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:
_registration = 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):
_response = 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):
_response = 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):
_response = 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.
Metadata
Release files for mock-response-delay 2026.9.12
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mock_response_delay-2026.9.12.tar.gz | 153.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mock_response_delay-2026.9.12-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 163.2 kB
Release files / mock_response_delay-2026.9.12.tar.gz
| Download URL | mock_response_delay-2026.9.12.tar.gz |
|---|---|
| Size | 153.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c48841a7f9e6f49eadc76cd789dc9d5894d70ab2a89ae64f82567f4bc890a8bb
|
|
BLAKE2b-256 checksum How to use checksums |
55879639579dc4ce58953c51add29336c3fa5d0fffe8e14e6903e79e8028a74b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.
Transparency logRelease files / mock_response_delay-2026.9.12-py3-none-any.whl
| Download URL | mock_response_delay-2026.9.12-py3-none-any.whl |
|---|---|
| Size | 9.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7ba63886d202eb9c2c0508cf650d8ce314cf404e0b3f66e748ebf244a3441fc9
|
|
BLAKE2b-256 checksum How to use checksums |
824541adceb85da9e1640b534ded333fb2be2d7256b6a1ef8b46d8d6bd215882
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.
Transparency log