Skip to content

Commit 313a4f4

Browse files
committed
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
1 parent ae1b9f6 commit 313a4f4

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

httpx/_transports/mock.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import datetime
34
import typing
45

56
from .._models import Request, Response
@@ -24,6 +25,7 @@ def handle_request(
2425
response = self.handler(request)
2526
if not isinstance(response, Response): # pragma: no cover
2627
raise TypeError("Cannot use an async handler in a sync Client")
28+
response.elapsed = datetime.timedelta()
2729
return response
2830

2931
async def handle_async_request(
@@ -40,4 +42,5 @@ async def handle_async_request(
4042
if not isinstance(response, Response):
4143
response = await response
4244

45+
response.elapsed = datetime.timedelta()
4346
return response

tests/client/test_client.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,3 +460,40 @@ def cp1252_but_no_content_type(request):
460460
assert response.reason_phrase == "OK"
461461
assert response.encoding == "ISO-8859-1"
462462
assert response.text == text
463+
464+
465+
def test_mock_transport_elapsed():
466+
"""Test that MockTransport sets the elapsed property.
467+
468+
Regression test for https://github.com/encode/httpx/issues/3712
469+
"""
470+
def handler(request):
471+
return httpx.Response(200, json={"text": "Hello, world!"})
472+
473+
transport = httpx.MockTransport(handler)
474+
with httpx.Client(transport=transport) as client:
475+
response = client.get("http://www.example.com")
476+
assert response.status_code == 200
477+
# MockTransport should set elapsed to timedelta(0)
478+
assert response.elapsed == timedelta(0)
479+
# Accessing elapsed should not raise RuntimeError
480+
assert isinstance(response.elapsed, timedelta)
481+
482+
483+
@pytest.mark.anyio
484+
async def test_async_mock_transport_elapsed():
485+
"""Test that MockTransport sets the elapsed property for async requests.
486+
487+
Regression test for https://github.com/encode/httpx/issues/3712
488+
"""
489+
def handler(request):
490+
return httpx.Response(200, json={"text": "Hello, world!"})
491+
492+
transport = httpx.MockTransport(handler)
493+
async with httpx.AsyncClient(transport=transport) as client:
494+
response = await client.get("http://www.example.com")
495+
assert response.status_code == 200
496+
# MockTransport should set elapsed to timedelta(0)
497+
assert response.elapsed == timedelta(0)
498+
# Accessing elapsed should not raise RuntimeError
499+
assert isinstance(response.elapsed, timedelta)

0 commit comments

Comments
 (0)