22Unit tests for :mod:`gateway_api.sds_search`.
33"""
44
5+ from unittest .mock import Mock , patch
6+
57import pytest
68from fhir .constants import FHIRSystem
79from fhir .r4 .resources .bundle import Bundle
810from pytest_mock import MockerFixture
911from stubs .sds .stub import SdsFhirApiStub
1012
1113from gateway_api .common .error import SdsRequestFailedError
12- from gateway_api .conftest import FakeResponse
14+ from gateway_api .conftest import FakeResponse , ScopedEnvVars
1315from gateway_api .get_structured_record import (
1416 ACCESS_RECORD_STRUCTURED_INTERACTION_ID ,
1517 SDS_SANDBOX_INTERACTION_ID ,
1618)
17- from gateway_api .sds import (
18- SdsClient ,
19- SdsSearchResults ,
20- )
19+ from gateway_api .sds import SdsClient , SdsSearchResults , get
2120
2221
2322@pytest .fixture
@@ -32,15 +31,13 @@ def stub(monkeypatch: pytest.MonkeyPatch) -> SdsFhirApiStub:
3231 return stub
3332
3433
35- def test_sds_client_get_org_details_success (
36- stub : SdsFhirApiStub ,
37- ) -> None :
34+ def test_sds_client_get_org_details_success (stub : SdsFhirApiStub ) -> None :
3835 """
3936 Test SdsClient can successfully look up organization details.
4037
4138 :param stub: SDS stub fixture.
4239 """
43- client = SdsClient (base_url = "https://test.com" )
40+ client = SdsClient (base_url = "https://test.com" , api_key = "example_api_key" )
4441
4542 result = client .get_org_details (ods_code = "PROVIDER" )
4643
@@ -56,9 +53,7 @@ def test_sds_client_get_org_details_success(
5653 )
5754
5855
59- def test_sds_client_get_org_details_with_endpoint (
60- stub : SdsFhirApiStub ,
61- ) -> None :
56+ def test_sds_client_get_org_details_with_endpoint (stub : SdsFhirApiStub ) -> None :
6257 """
6358 Test SdsClient retrieves endpoint when available.
6459
@@ -111,56 +106,49 @@ def test_sds_client_get_org_details_with_endpoint(
111106 },
112107 )
113108
114- client = SdsClient (base_url = "https://test.com" )
109+ client = SdsClient (base_url = "https://test.com" , api_key = "example_api_key" )
115110 result = client .get_org_details (ods_code = "TESTORG" )
116111
117112 assert result is not None
118113 assert result .asid == "999999999999"
119114 assert result .endpoint == "https://testorg.example.com/fhir"
120115
121116
122- def test_sds_client_sends_correct_headers (
123- stub : SdsFhirApiStub ,
124- ) -> None :
117+ def test_sds_client_sends_correct_headers (stub : SdsFhirApiStub ) -> None :
125118 """
126119 Test that SdsClient sends X-Correlation-Id and apikey headers when provided.
127120
128121 :param stub: SDS stub fixture.
129122 :param mock_requests_get: Capture fixture for request details.
130123 """
131- client = SdsClient (base_url = "https://test.com" )
124+ client = SdsClient (base_url = "https://test.com" , api_key = "example_api_key" )
132125
133126 correlation_id = "test-correlation-123"
134127 client .get_org_details (ods_code = "PROVIDER" , correlation_id = correlation_id )
135128
136129 # Check that the headers were
137130 assert stub .get_headers ["X-Correlation-Id" ] == correlation_id
138-
139- # In future when _get_api_key calls AWS secrets, this will break.
140- # That's a good thing, because we'll want to mock that call.
141- assert stub .get_headers ["apikey" ] == "test_api_key_DO_NOT_REPLACE_HERE"
131+ assert stub .get_headers ["apikey" ] == "example_api_key"
142132
143133
144- def test_sds_client_timeout_parameter (
145- stub : SdsFhirApiStub ,
146- ) -> None :
134+ def test_sds_client_timeout_parameter (stub : SdsFhirApiStub ) -> None :
147135 """
148136 Test that SdsClient passes timeout parameter to requests.
149137
150138 :param stub: SDS stub fixture.
151139 :param mock_requests_get: Capture fixture for request details.
152140 """
153- client = SdsClient (base_url = "https://test.com" , timeout = 30 )
141+ client = SdsClient (
142+ base_url = "https://test.com" , api_key = "example_api_key" , timeout = 30
143+ )
154144
155145 client .get_org_details (ods_code = "PROVIDER" , timeout = 60 )
156146
157147 # Check that the custom timeout was passed
158148 assert stub .get_timeout == 60
159149
160150
161- def test_sds_client_custom_service_interaction_id (
162- stub : SdsFhirApiStub ,
163- ) -> None :
151+ def test_sds_client_custom_service_interaction_id (stub : SdsFhirApiStub ) -> None :
164152 """
165153 Test that SdsClient uses custom interaction ID when provided.
166154
@@ -194,6 +182,7 @@ def test_sds_client_custom_service_interaction_id(
194182 client = SdsClient (
195183 base_url = "https://test.com" ,
196184 service_interaction_id = custom_interaction ,
185+ api_key = "example_api_key" ,
197186 )
198187
199188 result = client .get_org_details (ods_code = "CUSTOMINT" , get_endpoint = False )
@@ -209,16 +198,14 @@ def test_sds_client_custom_service_interaction_id(
209198 assert result .asid == "777777777777"
210199
211200
212- def test_sds_client_builds_correct_device_query_params (
213- stub : SdsFhirApiStub ,
214- ) -> None :
201+ def test_sds_client_builds_correct_device_query_params (stub : SdsFhirApiStub ) -> None :
215202 """
216203 Test that SdsClient builds Device query parameters correctly.
217204
218205 :param stub: SDS stub fixture.
219206 :param mock_requests_get: Capture fixture for request details.
220207 """
221- client = SdsClient (base_url = "https://test.com" )
208+ client = SdsClient (base_url = "https://test.com" , api_key = "example_api_key" )
222209
223210 client .get_org_details (ods_code = "PROVIDER" )
224211
@@ -268,7 +255,8 @@ def test_sds_client_uses_sandbox_interaction_id_for_sandbox_url(
268255 )
269256
270257 client = SdsClient (
271- base_url = "https://sandbox.api.service.nhs.uk/spine-directory/FHIR/R4"
258+ base_url = "https://sandbox.api.service.nhs.uk/spine-directory/FHIR/R4" ,
259+ api_key = "example_api_key" ,
272260 )
273261 result = client .get_org_details (ods_code = "SANDBOX_ORG" , get_endpoint = False )
274262
@@ -313,7 +301,7 @@ def get_without_apikey(
313301
314302 monkeypatch .setattr ("gateway_api.sds.client.get" , get_without_apikey )
315303
316- client = SdsClient (base_url = "https://test.com" )
304+ client = SdsClient (base_url = "https://test.com" , api_key = "example_api_key" )
317305
318306 with pytest .raises (SdsRequestFailedError , match = "SDS FHIR API request failed" ):
319307 client .get_org_details (ods_code = "PROVIDER" )
@@ -353,7 +341,7 @@ def test_sds_client_endpoint_entry_without_address_returns_none(
353341 },
354342 )
355343
356- client = SdsClient (base_url = "https://test.com" )
344+ client = SdsClient (base_url = "https://test.com" , api_key = "example_api_key" )
357345 result = client .get_org_details (ods_code = "NOADDR" )
358346
359347 assert result .asid == "111111111111"
@@ -369,7 +357,7 @@ def test_sds_client_empty_device_bundle_returns_none_asid() -> None:
369357
370358 :param stub: SDS stub fixture.
371359 """
372- client = SdsClient (base_url = "https://test.com" )
360+ client = SdsClient (base_url = "https://test.com" , api_key = "example_api_key" )
373361 # "UNKNOWN_ORG" has no seeded devices, so the bundle entry list will be empty
374362 result = client .get_org_details (ods_code = "UNKNOWN_ORG" , get_endpoint = False )
375363
@@ -398,24 +386,44 @@ def test_sds_client_no_endpoint_bundle_entries_returns_none_endpoint(
398386 )
399387 # Deliberately do not seed any endpoint for NOENDPOINT
400388
401- client = SdsClient (base_url = "https://test.com" )
389+ client = SdsClient (base_url = "https://test.com" , api_key = "example_api_key" )
402390 result = client .get_org_details (ods_code = "NOENDPOINT" )
403391
404392 assert result .asid == "222222222222"
405393 assert result .endpoint is None
406394
407395
408- def test_sds_client_respects_url (
409- mocker : MockerFixture ,
410- ) -> None :
396+ def test_sds_client_respects_url (mocker : MockerFixture ) -> None :
411397 empty_bundle = Bundle .empty ("searchset" ).model_dump ()
412398 mocked_get = mocker .patch (
413399 "gateway_api.sds.client.get" ,
414400 return_value = FakeResponse (status_code = 200 , headers = {}, _json = empty_bundle ),
415401 )
416402
417- client = SdsClient (base_url = "https://a.different.url/base" )
403+ client = SdsClient (
404+ base_url = "https://a.different.url/base" , api_key = "example_api_key"
405+ )
418406 _ = client .get_org_details (ods_code = "A12345" , get_endpoint = False )
419407
420408 actual_url = mocked_get .call_args .args [0 ]
409+ actual_headers = mocked_get .call_args .kwargs ["headers" ]
421410 assert actual_url == "https://a.different.url/base/Device"
411+ assert actual_headers ["apikey" ] == "example_api_key"
412+
413+
414+ @patch ("gateway_api.sds.client.SdsFhirApiStub" )
415+ @patch ("gateway_api.sds.client.external_sds_get" )
416+ def test_get_with_stub (mock_external_get : Mock , mock_stub : Mock ) -> None :
417+ with ScopedEnvVars ({"SDS_URL" : "stub" }):
418+ get ("https://example.com/" , headers = {}, params = {}, timeout = 10 )
419+ assert mock_stub .return_value .get .called
420+ assert not mock_external_get .called
421+
422+
423+ @patch ("gateway_api.sds.client.SdsFhirApiStub" )
424+ @patch ("gateway_api.sds.client.external_sds_get" )
425+ def test_get_without_stub (mock_external_get : Mock , mock_stub : Mock ) -> None :
426+ with ScopedEnvVars ({"SDS_URL" : "https://www.example.com/" }):
427+ get ("https://example.com/" , headers = {}, params = {}, timeout = 10 )
428+ assert mock_external_get .called
429+ assert not mock_stub .return_value .get .called
0 commit comments