Skip to main content

Build Status PyPI

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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mock_response_delay-2026.9.8.tar.gz (151.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mock_response_delay-2026.9.8-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

Details for the file mock_response_delay-2026.9.8.tar.gz.

File metadata

  • Download URL: mock_response_delay-2026.9.8.tar.gz
  • Upload date:
  • Size: 151.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for mock_response_delay-2026.9.8.tar.gz
Algorithm Hash digest
SHA256 c616ade93a1907a22911f29edd34c38bb51509c2ca4e595557699b7968640eb3
MD5 75af65f1278127ecae3da8e384d15b0f
BLAKE2b-256 d425702ad4e6cf8db6faac9d632d877d9689c38d56ae98e25386bce2e50091f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for mock_response_delay-2026.9.8.tar.gz:

Publisher: release.yml on adamtheturtle/mock-response-delay

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mock_response_delay-2026.9.8-py3-none-any.whl.

File metadata

File hashes

Hashes for mock_response_delay-2026.9.8-py3-none-any.whl
Algorithm Hash digest
SHA256 87b55b81f33a0e4ae12cff36a79990f4fdfbc077f977e97061382e743eff1c8f
MD5 f2f52fee2ad9afeb5da00bc4991c6a71
BLAKE2b-256 e85220279230c7a53655499b6222e37513a3e640a602c00d5dd542e3757afed0

See more details on using hashes here.

Provenance

The following attestation bundles were made for mock_response_delay-2026.9.8-py3-none-any.whl:

Publisher: release.yml on adamtheturtle/mock-response-delay

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

2026.9.8 This release

2 files

2026.9.7

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page