Skip to content

Commit 5039185

Browse files
mwdd146980claude
andcommitted
Migrate mock_http fixture and test files to MockHTTPResponse
Remaining changes from the httpx migration feature branch (#22676), split out from the base modules PR (#23299). Includes: - mock_http fixture in datadog_checks_dev (pytest plugin) - test_mock_http_patches_agentcheck test (depends on mock_http) - AgentCheck.http property update for mock_http support - MockResponse → MockHTTPResponse migration across ~40 test files - vault and traefik_mesh production code updates - OpenMetrics scraper updates for http_protocol compatibility Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6686cd3 commit 5039185

64 files changed

Lines changed: 603 additions & 656 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

airflow/tests/test_unit.py

Lines changed: 50 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,16 @@ def test_service_checks_cannot_connect(aggregator):
2626
'json_resp, expected_healthy_status, expected_healthy_value',
2727
[({'status': 'OK'}, AgentCheck.OK, 1), ({'status': 'KO'}, AgentCheck.CRITICAL, 0), ({}, AgentCheck.CRITICAL, 0)],
2828
)
29-
def test_service_checks_healthy_exp(aggregator, json_resp, expected_healthy_status, expected_healthy_value):
29+
def test_service_checks_healthy_exp(aggregator, mock_http, json_resp, expected_healthy_status, expected_healthy_value):
3030
instance = common.FULL_CONFIG['instances'][0]
3131
check = AirflowCheck('airflow', common.FULL_CONFIG, [instance])
3232

33-
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value=None):
34-
mock_session = mock.MagicMock()
35-
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=mock_session):
36-
mock_resp = mock.MagicMock(status_code=200)
37-
mock_resp.json.side_effect = [json_resp]
38-
mock_session.get.return_value = mock_resp
33+
mock_resp = mock.MagicMock(status_code=200)
34+
mock_resp.json.side_effect = [json_resp]
35+
mock_http.get.return_value = mock_resp
3936

40-
check.check(None)
37+
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value=None):
38+
check.check(None)
4139

4240
tags = ['key:my-tag', 'url:http://localhost:8080']
4341

@@ -54,65 +52,60 @@ def test_service_checks_healthy_exp(aggregator, json_resp, expected_healthy_stat
5452
],
5553
)
5654
def test_service_checks_healthy_stable(
57-
aggregator, metadb_status, scheduler_status, expected_healthy_status, expected_healthy_value
55+
aggregator, mock_http, metadb_status, scheduler_status, expected_healthy_status, expected_healthy_value
5856
): # Stable is only defined in the context of Airflow 2
5957
instance = common.FULL_CONFIG['instances'][0]
6058
check = AirflowCheck('airflow', common.FULL_CONFIG, [instance])
6159

62-
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value='2.6.2'):
63-
mock_session = mock.MagicMock()
64-
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=mock_session):
65-
mock_resp = mock.MagicMock(status_code=200)
66-
mock_resp.json.side_effect = [
67-
{'metadatabase': {'status': metadb_status}, 'scheduler': {'status': scheduler_status}},
68-
{'status': 'OK'},
69-
]
70-
mock_session.get.return_value = mock_resp
60+
mock_resp = mock.MagicMock(status_code=200)
61+
mock_resp.json.side_effect = [
62+
{'metadatabase': {'status': metadb_status}, 'scheduler': {'status': scheduler_status}},
63+
{'status': 'OK'},
64+
]
65+
mock_http.get.return_value = mock_resp
7166

72-
check.check(None)
67+
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value='2.6.2'):
68+
check.check(None)
7369

7470
tags = ['key:my-tag', 'url:http://localhost:8080']
7571

7672
aggregator.assert_service_check('airflow.healthy', expected_healthy_status, tags=tags, count=1)
7773
aggregator.assert_metric('airflow.healthy', expected_healthy_value, tags=tags, count=1)
7874

7975

80-
def test_dag_total_tasks(aggregator, task_instance):
76+
def test_dag_total_tasks(aggregator, mock_http, task_instance):
8177
instance = common.FULL_CONFIG['instances'][0]
8278
check = AirflowCheck('airflow', common.FULL_CONFIG, [instance])
8379

84-
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value='2.6.2'):
85-
req = mock.MagicMock()
86-
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=req):
87-
mock_resp = mock.MagicMock(status_code=200)
88-
mock_resp.json.side_effect = [
89-
{'metadatabase': {'status': 'healthy'}, 'scheduler': {'status': 'healthy'}},
90-
task_instance,
91-
]
92-
req.get.return_value = mock_resp
80+
mock_resp = mock.MagicMock(status_code=200)
81+
mock_resp.json.side_effect = [
82+
{'metadatabase': {'status': 'healthy'}, 'scheduler': {'status': 'healthy'}},
83+
task_instance,
84+
]
85+
mock_http.get.return_value = mock_resp
9386

94-
check.check(None)
87+
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value='2.6.2'):
88+
check.check(None)
9589

9690
aggregator.assert_metric('airflow.dag.task.total_running', value=1, count=1)
9791

9892

99-
def test_dag_task_ongoing_duration(aggregator, task_instance):
93+
def test_dag_task_ongoing_duration(aggregator, mock_http, task_instance):
10094
instance = common.FULL_CONFIG['instances'][0]
10195
check = AirflowCheck('airflow', common.FULL_CONFIG, [instance])
10296

97+
mock_resp = mock.MagicMock(status_code=200)
98+
mock_resp.json.side_effect = [
99+
{'metadatabase': {'status': 'healthy'}, 'scheduler': {'status': 'healthy'}},
100+
]
101+
mock_http.get.return_value = mock_resp
102+
103103
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value='2.6.2'):
104-
req = mock.MagicMock()
105-
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=req):
106-
mock_resp = mock.MagicMock(status_code=200)
107-
mock_resp.json.side_effect = [
108-
{'metadatabase': {'status': 'healthy'}, 'scheduler': {'status': 'healthy'}},
109-
]
110-
req.get.return_value = mock_resp
111-
with mock.patch(
112-
'datadog_checks.airflow.airflow.AirflowCheck._get_all_task_instances',
113-
return_value=task_instance.get('task_instances'),
114-
):
115-
check.check(None)
104+
with mock.patch(
105+
'datadog_checks.airflow.airflow.AirflowCheck._get_all_task_instances',
106+
return_value=task_instance.get('task_instances'),
107+
):
108+
check.check(None)
116109

117110
aggregator.assert_metric(
118111
'airflow.dag.task.ongoing_duration',
@@ -141,23 +134,21 @@ def test_dag_task_ongoing_duration(aggregator, task_instance):
141134
),
142135
],
143136
)
144-
def test_config_collect_ongoing_duration(collect_ongoing_duration, should_call_method):
137+
def test_config_collect_ongoing_duration(mock_http, collect_ongoing_duration, should_call_method):
145138
instance = {**common.FULL_CONFIG['instances'][0], 'collect_ongoing_duration': collect_ongoing_duration}
146139
check = AirflowCheck('airflow', common.FULL_CONFIG, [instance])
147140

141+
mock_resp = mock.MagicMock(status_code=200)
142+
mock_resp.json.side_effect = [
143+
{'metadatabase': {'status': 'healthy'}, 'scheduler': {'status': 'healthy'}},
144+
]
145+
mock_http.get.return_value = mock_resp
146+
148147
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value='2.6.2'):
149-
req = mock.MagicMock()
150-
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=req):
151-
mock_resp = mock.MagicMock(status_code=200)
152-
mock_resp.json.side_effect = [
153-
{'metadatabase': {'status': 'healthy'}, 'scheduler': {'status': 'healthy'}},
154-
]
155-
req.get.return_value = mock_resp
156-
157-
with mock.patch(
158-
'datadog_checks.airflow.airflow.AirflowCheck._get_all_task_instances'
159-
) as mock_get_all_task_instances:
160-
check.check(None)
161-
162-
# Assert method calls
163-
mock_get_all_task_instances.assert_has_calls(should_call_method, any_order=False)
148+
with mock.patch(
149+
'datadog_checks.airflow.airflow.AirflowCheck._get_all_task_instances'
150+
) as mock_get_all_task_instances:
151+
check.check(None)
152+
153+
# Assert method calls
154+
mock_get_all_task_instances.assert_has_calls(should_call_method, any_order=False)

appgate_sdp/tests/test_unit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def test_check_appgate_sdp(dd_run_check, aggregator, instance, mock_http_respons
3131
def test_emits_critical_service_check_when_service_is_down(dd_run_check, aggregator, instance, mock_http_response):
3232
mock_http_response(status_code=404)
3333
check = AppgateSDPCheck('appgate_sdp', {}, [instance])
34-
with pytest.raises(Exception, match='requests.exceptions.HTTPError'):
34+
with pytest.raises(Exception, match='HTTPStatusError'):
3535
dd_run_check(check)
3636
aggregator.assert_service_check('appgate_sdp.openmetrics.health', AppgateSDPCheck.CRITICAL)
3737

argo_workflows/tests/test_unit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,6 @@ def test_check_with_fixtures(dd_run_check, aggregator, instance, mock_http_respo
135135
def test_emits_critical_service_check_when_service_is_down(dd_run_check, aggregator, instance, mock_http_response):
136136
mock_http_response(status_code=404)
137137
check = ArgoWorkflowsCheck('argo_workflows', {}, [instance])
138-
with pytest.raises(Exception, match='requests.exceptions.HTTPError'):
138+
with pytest.raises(Exception, match='HTTPStatusError'):
139139
dd_run_check(check)
140140
aggregator.assert_service_check('argo_workflows.openmetrics.health', ArgoWorkflowsCheck.CRITICAL)

bentoml/tests/test_unit.py

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# (C) Datadog, Inc. 2025-present
22
# All rights reserved
33
# Licensed under a 3-clause BSD style license (see LICENSE)
4-
from unittest.mock import Mock, patch
4+
from unittest.mock import Mock
55

66
import pytest
7-
import requests
87

98
from datadog_checks.base.constants import ServiceCheck
9+
from datadog_checks.base.utils.http_exceptions import HTTPStatusError
1010
from datadog_checks.bentoml import BentomlCheck
1111
from datadog_checks.dev.utils import get_metadata_metrics
1212

@@ -21,26 +21,19 @@
2121
def test_bentoml_mock_metrics(dd_run_check, aggregator, mock_http_response):
2222
mock_http_response(file_path=get_fixture_path('metrics.txt'))
2323

24-
with patch('datadog_checks.bentoml.check.BentomlCheck.http') as mock_http:
25-
mock_response = type('MockResponse', (), {'status_code': 200})()
26-
mock_http.get.return_value = mock_response
27-
mock_http.get.return_value.raise_for_status = lambda: None
28-
29-
check = BentomlCheck('bentoml', {}, [OM_MOCKED_INSTANCE])
30-
dd_run_check(check)
24+
check = BentomlCheck('bentoml', {}, [OM_MOCKED_INSTANCE])
25+
dd_run_check(check)
3126

32-
for metric in METRICS:
33-
aggregator.assert_metric(metric)
27+
for metric in METRICS:
28+
aggregator.assert_metric(metric)
3429

35-
for metric in ENDPOINT_METRICS:
36-
aggregator.assert_metric(metric, value=1, tags=['test:tag', 'status_code:200'])
30+
for metric in ENDPOINT_METRICS:
31+
aggregator.assert_metric(metric, value=1, tags=['test:tag', 'status_code:200'])
3732

38-
aggregator.assert_all_metrics_covered()
39-
assert mock_http.get.call_count == 2
40-
aggregator.assert_metrics_using_metadata(get_metadata_metrics())
41-
aggregator.assert_all_metrics_covered()
42-
aggregator.assert_metric_has_tag('bentoml.service.request.count', 'bentoml_endpoint:/summarize')
43-
aggregator.assert_service_check('bentoml.openmetrics.health', ServiceCheck.OK)
33+
aggregator.assert_all_metrics_covered()
34+
aggregator.assert_metrics_using_metadata(get_metadata_metrics())
35+
aggregator.assert_metric_has_tag('bentoml.service.request.count', 'bentoml_endpoint:/summarize')
36+
aggregator.assert_service_check('bentoml.openmetrics.health', ServiceCheck.OK)
4437

4538

4639
def test_bentoml_mock_invalid_endpoint(dd_run_check, aggregator, mock_http_response):
@@ -53,21 +46,25 @@ def test_bentoml_mock_invalid_endpoint(dd_run_check, aggregator, mock_http_respo
5346

5447

5548
def test_bentoml_mock_valid_endpoint_invalid_health(dd_run_check, aggregator, mock_http_response):
56-
mock_http_response(file_path=get_fixture_path('metrics.txt'))
49+
session_get_mock = mock_http_response(file_path=get_fixture_path('metrics.txt'))
50+
metrics_response = session_get_mock.return_value
5751

5852
_err = Mock()
5953
_err.status_code = 500
60-
_http_err = requests.HTTPError("500 Internal Server Error")
61-
_http_err.response = _err
54+
_http_err = HTTPStatusError("500 Internal Server Error", response=_err)
6255
_err.raise_for_status.side_effect = _http_err
6356

64-
with patch('datadog_checks.bentoml.check.BentomlCheck.http') as mock_http:
65-
mock_http.get.return_value = _err
57+
def dispatch(url, **_):
58+
if '/livez' in url or '/readyz' in url:
59+
return _err
60+
return metrics_response
6661

67-
check = BentomlCheck('bentoml', {}, [OM_MOCKED_INSTANCE])
68-
dd_run_check(check)
62+
session_get_mock.side_effect = dispatch
63+
64+
check = BentomlCheck('bentoml', {}, [OM_MOCKED_INSTANCE])
65+
dd_run_check(check)
6966

70-
for metric in ENDPOINT_METRICS:
71-
aggregator.assert_metric(metric, value=0, tags=['test:tag', 'status_code:500'])
67+
for metric in ENDPOINT_METRICS:
68+
aggregator.assert_metric(metric, value=0, tags=['test:tag', 'status_code:500'])
7269

73-
aggregator.assert_service_check('bentoml.openmetrics.health', ServiceCheck.OK)
70+
aggregator.assert_service_check('bentoml.openmetrics.health', ServiceCheck.OK)

celery/tests/test_unit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def test_emits_critical_openemtrics_service_check_when_service_is_down(
4444
"""
4545
mock_http_response(status_code=404)
4646
check = CeleryCheck("celery", {}, [instance])
47-
with pytest.raises(Exception, match="requests.exceptions.HTTPError"):
47+
with pytest.raises(Exception, match="HTTPStatusError"):
4848
dd_run_check(check)
4949

5050
aggregator.assert_all_metrics_covered()

consul/tests/test_unit.py

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
# Licensed under a 3-clause BSD style license (see LICENSE)
44
import logging
55

6-
import mock
76
import pytest
87

98
from datadog_checks.consul import ConsulCheck
@@ -155,25 +154,25 @@ def test_get_nodes_with_service_critical(aggregator):
155154
aggregator.assert_metric('consul.catalog.services_count', value=1, tags=expected_tags)
156155

157156

158-
def test_consul_request(aggregator, instance, mocker):
157+
def test_consul_request(aggregator, instance, mocker, mock_http):
159158
consul_check = ConsulCheck(common.CHECK_NAME, {}, [consul_mocks.MOCK_CONFIG])
160159
mocker.patch("datadog_checks.base.utils.serialization.json.loads")
161-
with mock.patch("datadog_checks.consul.consul.requests.Session.get") as mock_requests_get:
160+
161+
consul_check.consul_request("foo")
162+
url = "{}/{}".format(instance["url"], "foo")
163+
aggregator.assert_service_check("consul.can_connect", ConsulCheck.OK, tags=["url:{}".format(url)], count=1)
164+
165+
aggregator.reset()
166+
mock_http.get.side_effect = Exception("message")
167+
with pytest.raises(Exception):
162168
consul_check.consul_request("foo")
163-
url = "{}/{}".format(instance["url"], "foo")
164-
aggregator.assert_service_check("consul.can_connect", ConsulCheck.OK, tags=["url:{}".format(url)], count=1)
165-
166-
aggregator.reset()
167-
mock_requests_get.side_effect = Exception("message")
168-
with pytest.raises(Exception):
169-
consul_check.consul_request("foo")
170-
aggregator.assert_service_check(
171-
"consul.can_connect",
172-
ConsulCheck.CRITICAL,
173-
tags=["url:{}".format(url)],
174-
count=1,
175-
message="Consul request to {} failed: message".format(url),
176-
)
169+
aggregator.assert_service_check(
170+
"consul.can_connect",
171+
ConsulCheck.CRITICAL,
172+
tags=["url:{}".format(url)],
173+
count=1,
174+
message="Consul request to {} failed: message".format(url),
175+
)
177176

178177

179178
def test_service_checks(aggregator):
@@ -648,26 +647,13 @@ def test_network_latency_node_name(
648647
),
649648
],
650649
)
651-
def test_config(test_case, extra_config, expected_http_kwargs, mocker):
650+
def test_config(test_case, extra_config, expected_http_kwargs):
652651
instance = extra_config
653652
check = ConsulCheck(common.CHECK_NAME, {}, instances=[instance])
654-
mocker.patch("datadog_checks.base.utils.serialization.json.loads")
655653

656-
with mock.patch('datadog_checks.base.utils.http.requests.Session') as session:
657-
mock_session = mock.MagicMock()
658-
session.return_value = mock_session
659-
mock_session.get.return_value = mock.MagicMock(status_code=200)
660-
661-
check.check(None)
662-
663-
http_wargs = {
664-
'auth': mock.ANY,
665-
'cert': mock.ANY,
666-
'headers': mock.ANY,
667-
'proxies': mock.ANY,
668-
'timeout': mock.ANY,
669-
'verify': mock.ANY,
670-
'allow_redirects': mock.ANY,
671-
}
672-
http_wargs.update(expected_http_kwargs)
673-
mock_session.get.assert_called_with('/v1/status/leader', **http_wargs)
654+
for key, value in expected_http_kwargs.items():
655+
if key == 'headers':
656+
for h_key, h_value in value.items():
657+
assert check.http.get_header(h_key) == h_value
658+
else:
659+
assert check.http.options[key] == value

couch/tests/test_unit.py

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from copy import deepcopy
55
from unittest.mock import MagicMock
66

7-
import mock
87
import pytest
98

109
from datadog_checks.couch import CouchDb
@@ -30,24 +29,8 @@ def test_config(test_case, extra_config, expected_http_kwargs):
3029
instance.update(extra_config)
3130
check = CouchDb(common.CHECK_NAME, {}, instances=[instance])
3231

33-
r = mock.MagicMock()
34-
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=r):
35-
r.get.return_value = mock.MagicMock(status_code=200, content='{}')
36-
37-
check.check(instance)
38-
39-
http_wargs = {
40-
'auth': mock.ANY,
41-
'cert': mock.ANY,
42-
'headers': mock.ANY,
43-
'proxies': mock.ANY,
44-
'timeout': mock.ANY,
45-
'verify': mock.ANY,
46-
'allow_redirects': mock.ANY,
47-
}
48-
http_wargs.update(expected_http_kwargs)
49-
50-
r.get.assert_called_with('http://{}:5984/_all_dbs/'.format(common.HOST), **http_wargs)
32+
for key, value in expected_http_kwargs.items():
33+
assert check.http.options[key] == value
5134

5235

5336
def test_new_version_system_metrics(load_test_data):

0 commit comments

Comments
 (0)