This commit is contained in:
Jun-te Kim 2026-05-13 11:41:21 +00:00
parent c347865b9e
commit ff4ad07a2b

View file

@ -8,12 +8,13 @@ from datatypes.epc.domain.epc_property_data import EpcPropertyData
from backend.epc_client.tests.conftest import make_search_row
def _mock_response(status_code=200, json_data=None):
def _mock_response(status_code=200, json_data=None, headers=None):
resp = MagicMock()
resp.status_code = status_code
resp.is_success = 200 <= status_code < 300
resp.json.return_value = json_data or {}
resp.text = str(json_data)
resp.headers = headers or {}
return resp
@ -63,6 +64,89 @@ def test_get_by_certificate_number_retries_on_429_and_succeeds(
assert isinstance(result, EpcPropertyData)
# ---------------------------------------------------------------------------
# Test 3b: 429 with Retry-After header → sleeps for that value
# ---------------------------------------------------------------------------
def test_429_retry_after_header_drives_sleep_duration(
epc_service, rdsap_21_0_1_cert
):
cert_response = {"data": rdsap_21_0_1_cert}
responses = [
_mock_response(429, headers={"Retry-After": "7"}),
_mock_response(200, cert_response),
]
with patch("httpx.get", side_effect=responses), patch(
"backend.epc_client._retry.time.sleep"
) as mock_sleep:
epc_service.get_by_certificate_number("CERT-001")
mock_sleep.assert_called_once_with(7.0)
# ---------------------------------------------------------------------------
# Test 3c: 429 without Retry-After → falls back to exponential backoff
# ---------------------------------------------------------------------------
def test_429_without_retry_after_uses_exponential_backoff(
epc_service, rdsap_21_0_1_cert
):
cert_response = {"data": rdsap_21_0_1_cert}
responses = [
_mock_response(429),
_mock_response(429),
_mock_response(200, cert_response),
]
with patch("httpx.get", side_effect=responses), patch(
"backend.epc_client._retry.time.sleep"
) as mock_sleep:
epc_service.get_by_certificate_number("CERT-001")
assert mock_sleep.call_args_list == [call(1.0), call(2.0)]
# ---------------------------------------------------------------------------
# Test 3d: malformed Retry-After header → falls back to exponential backoff
# ---------------------------------------------------------------------------
def test_429_malformed_retry_after_falls_back_to_backoff(
epc_service, rdsap_21_0_1_cert
):
cert_response = {"data": rdsap_21_0_1_cert}
responses = [
_mock_response(429, headers={"Retry-After": "Wed, 21 Oct 2026 07:28:00 GMT"}),
_mock_response(200, cert_response),
]
with patch("httpx.get", side_effect=responses), patch(
"backend.epc_client._retry.time.sleep"
) as mock_sleep:
epc_service.get_by_certificate_number("CERT-001")
mock_sleep.assert_called_once_with(1.0)
# ---------------------------------------------------------------------------
# Test 3e: Retry-After capped by max_backoff to avoid hostile/buggy values
# ---------------------------------------------------------------------------
def test_429_retry_after_capped_by_max_backoff(epc_service, rdsap_21_0_1_cert):
cert_response = {"data": rdsap_21_0_1_cert}
responses = [
_mock_response(429, headers={"Retry-After": "9999"}),
_mock_response(200, cert_response),
]
with patch("httpx.get", side_effect=responses), patch(
"backend.epc_client._retry.time.sleep"
) as mock_sleep:
epc_service.get_by_certificate_number("CERT-001")
mock_sleep.assert_called_once_with(60.0)
# ---------------------------------------------------------------------------
# Test 4: get_by_uprn empty search → None
# ---------------------------------------------------------------------------