Skip to content

Commit 06066d9

Browse files
adamtheturtleclaude
andcommitted
Add injectable sleep_fn parameter to MockVWS
Enable deterministic test-time delay handling by allowing callers to inject a custom sleep strategy. This avoids the need for monkeypatching and enables virtual time control with libraries like freezegun. - Add sleep_fn parameter to MockVWS.__init__ with default time.sleep - Pass sleep_fn through to _wrap_callback for both timeout and delay paths - Add tests verifying injected sleep_fn is called on both success and timeout paths - Update changelog Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 825d206 commit 06066d9

3 files changed

Lines changed: 60 additions & 2 deletions

File tree

CHANGELOG.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Changelog
44
Next
55
----
66

7+
- Add ``sleep_fn`` parameter to ``MockVWS`` for injecting a custom delay strategy, enabling deterministic and fast tests without monkeypatching.
8+
79
2026.02.15.3
810
------------
911

src/mock_vws/_requests_mock_server/decorators.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def __init__(
7070
target_tracking_rater: TargetTrackingRater = _BRISQUE_TRACKING_RATER,
7171
real_http: bool = False,
7272
response_delay_seconds: float = 0.0,
73+
sleep_fn: Callable[[float], None] = time.sleep,
7374
) -> None:
7475
"""Route requests to Vuforia's Web Service APIs to fakes of those
7576
APIs.
@@ -91,13 +92,18 @@ def __init__(
9192
target_tracking_rater: A callable for rating targets for tracking.
9293
response_delay_seconds: The number of seconds to delay each
9394
response by. This can be used to test timeout handling.
95+
sleep_fn: The function to use for sleeping during response
96+
delays. Defaults to ``time.sleep``. Inject a custom
97+
function to control virtual time in tests without
98+
monkeypatching.
9499
95100
Raises:
96101
MissingSchemeError: There is no scheme in a given URL.
97102
"""
98103
super().__init__()
99104
self._real_http = real_http
100105
self._response_delay_seconds = response_delay_seconds
106+
self._sleep_fn = sleep_fn
101107
self._mock: RequestsMock
102108
self._target_manager = TargetManager()
103109

@@ -136,6 +142,7 @@ def add_database(self, database: VuforiaDatabase) -> None:
136142
def _wrap_callback(
137143
callback: _Callback,
138144
delay_seconds: float,
145+
sleep_fn: Callable[[float], None],
139146
) -> _Callback:
140147
"""Wrap a callback to add a response delay."""
141148

@@ -159,11 +166,11 @@ def wrapped(
159166
effective = float(timeout)
160167

161168
if effective is not None and delay_seconds > effective:
162-
time.sleep(effective)
169+
sleep_fn(effective)
163170
raise requests.exceptions.Timeout
164171

165172
result = callback(request)
166-
time.sleep(delay_seconds)
173+
sleep_fn(delay_seconds)
167174
return result
168175

169176
return wrapped
@@ -195,6 +202,7 @@ def __enter__(self) -> Self:
195202
callback=self._wrap_callback(
196203
callback=original_callback,
197204
delay_seconds=self._response_delay_seconds,
205+
sleep_fn=self._sleep_fn,
198206
),
199207
content_type=None,
200208
)

tests/mock_vws/test_requests_mock_usage.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,54 @@ def test_delay_with_tuple_timeout() -> None:
195195
timeout=(5.0, 0.1),
196196
)
197197

198+
@staticmethod
199+
def test_custom_sleep_fn_called_on_delay() -> None:
200+
"""
201+
When a custom ``sleep_fn`` is provided, it is called instead of
202+
``time.sleep`` for the non-timeout delay path.
203+
"""
204+
calls: list[float] = []
205+
with MockVWS(
206+
response_delay_seconds=5.0,
207+
sleep_fn=calls.append,
208+
):
209+
requests.get(
210+
url="https://vws.vuforia.com/summary",
211+
headers={
212+
"Date": rfc_1123_date(),
213+
"Authorization": "bad_auth_token",
214+
},
215+
data=b"",
216+
timeout=30,
217+
)
218+
assert calls == [5.0]
219+
220+
@staticmethod
221+
def test_custom_sleep_fn_called_on_timeout() -> None:
222+
"""
223+
When a custom ``sleep_fn`` is provided, it is called instead of
224+
``time.sleep`` for the timeout path.
225+
"""
226+
calls: list[float] = []
227+
with (
228+
MockVWS(
229+
response_delay_seconds=5.0,
230+
sleep_fn=calls.append,
231+
),
232+
pytest.raises(expected_exception=requests.exceptions.Timeout),
233+
):
234+
requests.get(
235+
url="https://vws.vuforia.com/summary",
236+
headers={
237+
"Date": rfc_1123_date(),
238+
"Authorization": "bad_auth_token",
239+
},
240+
data=b"",
241+
timeout=1.0,
242+
)
243+
# sleep_fn should have been called with the effective timeout
244+
assert calls == [1.0]
245+
198246

199247
class TestProcessingTime:
200248
"""Tests for the time taken to process targets in the mock."""

0 commit comments

Comments
 (0)