Fix MockTransport not setting elapsed property

MockTransport now automatically sets response.elapsed to timedelta(0)
for both sync and async requests, matching the behavior of real
transports and eliminating the need for boilerplate code in handlers.

Previously, accessing response.elapsed on MockTransport responses
would raise RuntimeError. Now it returns timedelta(0) by default,
which is the expected behavior for mocked requests with no actual
network I/O.

Fixes #3712
This commit is contained in:
Varun Chawla 2026-02-07 17:14:33 -08:00
parent b5addb64f0
commit 50c162cfb4
No known key found for this signature in database
2 changed files with 40 additions and 0 deletions

View File

@ -1,5 +1,6 @@
from __future__ import annotations
import datetime
import typing
from .._models import Request, Response
@ -24,6 +25,7 @@ class MockTransport(AsyncBaseTransport, BaseTransport):
response = self.handler(request)
if not isinstance(response, Response): # pragma: no cover
raise TypeError("Cannot use an async handler in a sync Client")
response.elapsed = datetime.timedelta()
return response
async def handle_async_request(
@ -40,4 +42,5 @@ class MockTransport(AsyncBaseTransport, BaseTransport):
if not isinstance(response, Response):
response = await response
response.elapsed = datetime.timedelta()
return response

View File

@ -460,3 +460,40 @@ def test_client_decode_text_using_explicit_encoding():
assert response.reason_phrase == "OK"
assert response.encoding == "ISO-8859-1"
assert response.text == text
def test_mock_transport_elapsed():
"""Test that MockTransport sets the elapsed property.
Regression test for https://github.com/encode/httpx/issues/3712
"""
def handler(request):
return httpx.Response(200, json={"text": "Hello, world!"})
transport = httpx.MockTransport(handler)
with httpx.Client(transport=transport) as client:
response = client.get("http://www.example.com")
assert response.status_code == 200
# MockTransport should set elapsed to timedelta(0)
assert response.elapsed == timedelta(0)
# Accessing elapsed should not raise RuntimeError
assert isinstance(response.elapsed, timedelta)
@pytest.mark.anyio
async def test_async_mock_transport_elapsed():
"""Test that MockTransport sets the elapsed property for async requests.
Regression test for https://github.com/encode/httpx/issues/3712
"""
def handler(request):
return httpx.Response(200, json={"text": "Hello, world!"})
transport = httpx.MockTransport(handler)
async with httpx.AsyncClient(transport=transport) as client:
response = await client.get("http://www.example.com")
assert response.status_code == 200
# MockTransport should set elapsed to timedelta(0)
assert response.elapsed == timedelta(0)
# Accessing elapsed should not raise RuntimeError
assert isinstance(response.elapsed, timedelta)