Skip to content

Commit f2eaf69

Browse files
mwdd146980claude
andcommitted
Add mock_http fixture to datadog_checks_dev
The mock_http fixture depends on http_protocol (added in this PR) and is needed by test_http_testing.py. Move it here from the remaining changes PR so the test suite passes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 53ae1af commit f2eaf69

2 files changed

Lines changed: 55 additions & 14 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add mock_http fixture for library-agnostic HTTP client mocking in integration tests.

datadog_checks_dev/datadog_checks/dev/plugin/pytest.py

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333

3434
__aggregator = None
3535
__datadog_agent = None
36-
MockResponse = None
36+
MockHTTPResponse = None
37+
38+
_DEFAULT_MOCK_METHOD = 'requests.Session.get' # TODO(httpx-migration): update when backend changes
3739

3840

3941
@pytest.fixture
@@ -286,37 +288,75 @@ def dd_default_hostname():
286288

287289
@pytest.fixture
288290
def mock_response():
289-
# Lazily import `requests` as it may be costly under certain conditions
290-
global MockResponse
291-
if MockResponse is None:
292-
from datadog_checks.dev.http import MockResponse
291+
global MockHTTPResponse
292+
if MockHTTPResponse is None:
293+
from datadog_checks.base.utils.http_testing import MockHTTPResponse
293294

294-
yield MockResponse
295+
yield MockHTTPResponse
295296

296297

297298
@pytest.fixture
298299
def mock_http_response(mocker, mock_response):
299300
yield lambda *args, **kwargs: mocker.patch(
300-
kwargs.pop('method', 'requests.Session.get'), return_value=mock_response(*args, **kwargs)
301+
kwargs.pop('method', _DEFAULT_MOCK_METHOD), return_value=mock_response(*args, **kwargs)
301302
)
302303

303304

305+
@pytest.fixture
306+
def mock_http(mocker):
307+
from unittest.mock import PropertyMock, create_autospec
308+
309+
from datadog_checks.base.checks.base import AgentCheck
310+
from datadog_checks.base.utils.http_protocol import HTTPClientProtocol
311+
312+
client = create_autospec(HTTPClientProtocol)
313+
# Protocol annotations are not picked up by create_autospec, so set options explicitly.
314+
client.options = {
315+
'auth': None,
316+
'cert': None,
317+
'headers': {},
318+
'proxies': None,
319+
'timeout': (10.0, 10.0),
320+
'verify': True,
321+
'allow_redirects': True,
322+
}
323+
324+
def _get_header(name, default=None):
325+
for key, value in client.options['headers'].items():
326+
if key.lower() == name.lower():
327+
return value
328+
return default
329+
330+
def _set_header(name, value):
331+
for key in list(client.options['headers']):
332+
if key.lower() == name.lower():
333+
client.options['headers'][key] = value
334+
return
335+
client.options['headers'][name] = value
336+
337+
client.get_header.side_effect = _get_header
338+
client.set_header.side_effect = _set_header
339+
client.options_method.side_effect = NotImplementedError('HTTP OPTIONS not yet supported in mock_http')
340+
mocker.patch.object(AgentCheck, 'http', new_callable=PropertyMock, return_value=client)
341+
return client
342+
343+
304344
@pytest.fixture
305345
def mock_http_response_per_endpoint(mocker, mock_response):
306346
@overload
307347
def _mock(
308-
responses_by_endpoint: Dict[str, list[MockResponse]],
348+
responses_by_endpoint: Dict[str, list[MockHTTPResponse]],
309349
*,
310350
mode: Literal["default"],
311-
default_response: MockResponse,
351+
default_response: MockHTTPResponse,
312352
method: str = ...,
313353
url_arg_index: int = ...,
314354
url_kwarg_name: str = ...,
315355
strict: bool = ...,
316356
): ...
317357
@overload
318358
def _mock(
319-
responses_by_endpoint: Dict[str, list[MockResponse]],
359+
responses_by_endpoint: Dict[str, list[MockHTTPResponse]],
320360
*,
321361
mode: Literal["cycle", "exhaust"],
322362
default_response: None = None,
@@ -326,10 +366,10 @@ def _mock(
326366
strict: bool = ...,
327367
): ...
328368
def _mock(
329-
responses_by_endpoint: Dict[str, list[MockResponse]],
369+
responses_by_endpoint: Dict[str, list[MockHTTPResponse]],
330370
mode: Literal['cycle', 'exhaust', 'default'] = 'cycle',
331-
default_response: MockResponse | None = None,
332-
method: str = 'requests.Session.get',
371+
default_response: MockHTTPResponse | None = None,
372+
method: str = _DEFAULT_MOCK_METHOD,
333373
url_arg_index: int = 1,
334374
url_kwarg_name: str = "url",
335375
strict: bool = True,
@@ -364,7 +404,7 @@ def side_effect(*args, **kwargs):
364404
if strict:
365405
raise ValueError(f"Endpoint {url} not found in mocked responses")
366406
else:
367-
return MockResponse(status_code=404)
407+
return mock_response(status_code=404)
368408
else:
369409
try:
370410
return next(queues[url])

0 commit comments

Comments
 (0)