From b744503b4acacdea6edd0b05e2ed5c206075ef13 Mon Sep 17 00:00:00 2001 From: Ian Robinson <267046044+ian-robinson-35@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:19:23 +0000 Subject: [PATCH 1/7] Working connection --- Makefile | 3 ++ .../Steel_Thread/environments/localInt.yml | 8 +++++ gateway-api/src/gateway_api/controller.py | 2 +- gateway-api/src/gateway_api/sds/client.py | 10 ++---- .../stubs/stubs/data/bundles/bundles.py | 1 + .../stubs/data/patients/int_9658218865.json | 35 +++++++++++++++++++ .../stubs/stubs/data/patients/patients.py | 1 + gateway-api/stubs/stubs/pds/stub.py | 1 + gateway-api/stubs/stubs/provider/stub.py | 6 ++++ 9 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 bruno/gateway-api/collections/Steel_Thread/environments/localInt.yml create mode 100644 gateway-api/stubs/stubs/data/patients/int_9658218865.json diff --git a/Makefile b/Makefile index 16da7fd5..99e6a5eb 100644 --- a/Makefile +++ b/Makefile @@ -79,6 +79,9 @@ deploy: clean build # Deploy the project artefact to the target environment @Pip if [[ -n "$${STUB_SDS}" ]]; then \ ENVIRONMENT_STRING="$${ENVIRONMENT_STRING} -e STUB_SDS=$${STUB_SDS}" ; \ fi ; \ + if [[ -n "$${SDS_API_KEY}" ]]; then \ + ENVIRONMENT_STRING="$${ENVIRONMENT_STRING} -e SDS_API_KEY=$${SDS_API_KEY}" ; \ + fi ; \ if [[ -n "$${CDG_DEBUG}" ]]; then \ ENVIRONMENT_STRING="$${ENVIRONMENT_STRING} -e CDG_DEBUG=$${CDG_DEBUG}" ; \ fi ; \ diff --git a/bruno/gateway-api/collections/Steel_Thread/environments/localInt.yml b/bruno/gateway-api/collections/Steel_Thread/environments/localInt.yml new file mode 100644 index 00000000..56a8c8e8 --- /dev/null +++ b/bruno/gateway-api/collections/Steel_Thread/environments/localInt.yml @@ -0,0 +1,8 @@ +name: localInt +variables: + - name: base_url + value: http://localhost:5000 + - name: nhs_number + value: "9658218865" + - name: from_ods + value: A20047 diff --git a/gateway-api/src/gateway_api/controller.py b/gateway-api/src/gateway_api/controller.py index ac37c16e..b7f9f420 100644 --- a/gateway-api/src/gateway_api/controller.py +++ b/gateway-api/src/gateway_api/controller.py @@ -28,7 +28,7 @@ class Controller: def __init__( self, pds_base_url: str = PdsClient.SANDBOX_URL, - sds_base_url: str = SdsClient.SANDBOX_URL, + sds_base_url: str = SdsClient.INT_URL, timeout: int = 10, ) -> None: """ diff --git a/gateway-api/src/gateway_api/sds/client.py b/gateway-api/src/gateway_api/sds/client.py index 22de0009..57325f25 100644 --- a/gateway-api/src/gateway_api/sds/client.py +++ b/gateway-api/src/gateway_api/sds/client.py @@ -80,7 +80,7 @@ class SdsClient: def __init__( self, - base_url: str = SANDBOX_URL, + base_url: str = INT_URL, timeout: int = 10, service_interaction_id: str | None = None, ) -> None: @@ -161,14 +161,8 @@ def get_org_details( def _get_api_key() -> str: """ Retrieve the API key to use for SDS requests. - - This is a placeholder at present because we don't have a real API key. - Ultimately it will probably obtain the key from AWS secrets """ - - # TODO [GPCAPIM-366]: Obtain key from AWS secrets - # DO NOT PUT A REAL KEY HERE, IT WILL BE VISIBLE ON GITHUB - return "test_api_key_DO_NOT_REPLACE_HERE" + return os.environ.get("SDS_API_KEY", "") def _query_sds( self, diff --git a/gateway-api/stubs/stubs/data/bundles/bundles.py b/gateway-api/stubs/stubs/data/bundles/bundles.py index d714c29d..62574e31 100644 --- a/gateway-api/stubs/stubs/data/bundles/bundles.py +++ b/gateway-api/stubs/stubs/data/bundles/bundles.py @@ -18,3 +18,4 @@ def _wrap_patient_in_bundle(patient: dict[str, Any]) -> dict[str, Any]: } ALICE_JONES_9999999999 = _wrap_patient_in_bundle(Patients.ALICE_JONES_9999999999) + INT_9658218865 = _wrap_patient_in_bundle(Patients.INT_9658218865) diff --git a/gateway-api/stubs/stubs/data/patients/int_9658218865.json b/gateway-api/stubs/stubs/data/patients/int_9658218865.json new file mode 100644 index 00000000..54800668 --- /dev/null +++ b/gateway-api/stubs/stubs/data/patients/int_9658218865.json @@ -0,0 +1,35 @@ +{ + "resourceType": "Patient", + "id": "9658218865", + "meta": { + "versionId": "1", + "lastUpdated": "2020-01-01T00:00:00Z" + }, + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9658218865" + } + ], + "name": [ + { + "use": "official", + "family": "Samual", + "given": ["Lucien"], + "period": {"start": "1900-01-01", "end": "9999-12-31"} + } + ], + "gender": "male", + "birthDate": "1938-12-11", + "generalPractitioner": [ + { + "id": "1", + "type": "Organization", + "identifier": { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "A20047", + "period": {"start": "2020-01-01", "end": "9999-12-31"} + } + } + ] +} diff --git a/gateway-api/stubs/stubs/data/patients/patients.py b/gateway-api/stubs/stubs/data/patients/patients.py index 1b6a5a0d..a16141d1 100644 --- a/gateway-api/stubs/stubs/data/patients/patients.py +++ b/gateway-api/stubs/stubs/data/patients/patients.py @@ -27,3 +27,4 @@ def load_patient(filename: str) -> dict[str, Any]: ) ALICE_JONES_9999999999 = load_patient("alice_jones_9999999999.json") ORANGE_BOX_TRIGGER_9690937278 = load_patient("orange_box_trigger_9690937278.json") + INT_9658218865 = load_patient("int_9658218865.json") diff --git a/gateway-api/stubs/stubs/pds/stub.py b/gateway-api/stubs/stubs/pds/stub.py index 09ab014b..e26b09dd 100644 --- a/gateway-api/stubs/stubs/pds/stub.py +++ b/gateway-api/stubs/stubs/pds/stub.py @@ -53,6 +53,7 @@ def __init__(self, strict_headers: bool = True) -> None: ("9000000012", Patients.INDUCE_PROVIDER_ERROR_9000000012), ("9000000013", Patients.BLANK_ENDPOINT_SDS_RESULT_9000000013), ("9690937278", Patients.ORANGE_BOX_TRIGGER_9690937278), + ("9658218865", Patients.INT_9658218865), ] for nhs_number, patient in test_patients: self.upsert_patient( diff --git a/gateway-api/stubs/stubs/provider/stub.py b/gateway-api/stubs/stubs/provider/stub.py index 78d864e0..d11de632 100644 --- a/gateway-api/stubs/stubs/provider/stub.py +++ b/gateway-api/stubs/stubs/provider/stub.py @@ -279,6 +279,12 @@ def access_record_structured( json_data=Bundles.ALICE_JONES_9999999999, ) + if nhs_number == "9658218865": + return self._create_response( + status_code=200, + json_data=Bundles.INT_9658218865, + ) + return self._create_response( status_code=404, json_data={ From ceb5bfec89500bf25b60a8ac0ea18dc226f3ab03 Mon Sep 17 00:00:00 2001 From: Ian Robinson <267046044+ian-robinson-35@users.noreply.github.com> Date: Thu, 23 Apr 2026 14:15:00 +0000 Subject: [PATCH 2/7] Tidy up --- gateway-api/src/gateway_api/sds/client.py | 29 +++++++++++++---------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/gateway-api/src/gateway_api/sds/client.py b/gateway-api/src/gateway_api/sds/client.py index 57325f25..2ce38289 100644 --- a/gateway-api/src/gateway_api/sds/client.py +++ b/gateway-api/src/gateway_api/sds/client.py @@ -15,23 +15,28 @@ from fhir import Resource from fhir.constants import FHIRSystem from fhir.r4 import Bundle, Device, Endpoint -from requests import HTTPError +from requests import HTTPError, Response +from requests import get as external_sds_get +from stubs import SdsFhirApiStub from gateway_api.common.error import SdsRequestFailedError from gateway_api.get_structured_record import ACCESS_RECORD_STRUCTURED_INTERACTION_ID from gateway_api.sds.search_results import SdsSearchResults -# TODO [GPCAPIM-359]: Once stub servers/containers made for PDS, SDS and provider -# we should remove the STUB_SDS environment variable and just -# use the stub client -STUB_SDS = os.environ.get("STUB_SDS", "false").lower() == "true" -if not STUB_SDS: - from requests import get -else: - from stubs import SdsFhirApiStub - sds = SdsFhirApiStub() - get = sds.get # type: ignore +def get( + url: str, + headers: dict[str, str], + params: dict[str, str], + timeout: int, +) -> Response: + STUB_SDS = os.environ.get("STUB_SDS", "false").lower() == "true" + if not STUB_SDS: + return external_sds_get(url, headers=headers, params=params, timeout=timeout) + else: + return SdsFhirApiStub().get( + url, headers=headers, params=params, timeout=timeout + ) class SdsResourceType(StrEnum): @@ -80,7 +85,7 @@ class SdsClient: def __init__( self, - base_url: str = INT_URL, + base_url: str = SANDBOX_URL, timeout: int = 10, service_interaction_id: str | None = None, ) -> None: From 5d720ba561fb8c6b31c0c511682078d57b3b77b9 Mon Sep 17 00:00:00 2001 From: Ian Robinson <267046044+ian-robinson-35@users.noreply.github.com> Date: Thu, 23 Apr 2026 14:36:49 +0000 Subject: [PATCH 3/7] Improve test --- gateway-api/src/gateway_api/conftest.py | 31 +++++++++++++++++++ .../src/gateway_api/sds/test_client.py | 17 +++++----- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/gateway-api/src/gateway_api/conftest.py b/gateway-api/src/gateway_api/conftest.py index ed7844f0..4bd4ceb3 100644 --- a/gateway-api/src/gateway_api/conftest.py +++ b/gateway-api/src/gateway_api/conftest.py @@ -1,7 +1,10 @@ """Pytest configuration and shared fixtures for gateway API tests.""" import json +import os +from collections.abc import Mapping from dataclasses import dataclass +from types import TracebackType from typing import Any import pytest @@ -14,6 +17,34 @@ from gateway_api.clinical_jwt import JWT +class NewEnvVars: + def __init__(self, new_env_vars: Mapping[str, str | None]) -> None: + self.new_env_vars = new_env_vars + self.original_env_vars = {} + for key in new_env_vars: + if key in os.environ: + self.original_env_vars[key] = os.environ[key] + + def __enter__(self) -> "NewEnvVars": + for key, value in self.new_env_vars.items(): + if value is None and key in os.environ: + del os.environ[key] + elif value is not None: + os.environ[key] = value + return self + + def __exit__( + self, + _type: type[BaseException] | None, + _value: BaseException | None, + _traceback: TracebackType | None, + ) -> None: + for key in self.new_env_vars: + if key in os.environ: + del os.environ[key] + os.environ.update(self.original_env_vars) + + @dataclass class FakeResponse: """ diff --git a/gateway-api/src/gateway_api/sds/test_client.py b/gateway-api/src/gateway_api/sds/test_client.py index 76019991..4ad86371 100644 --- a/gateway-api/src/gateway_api/sds/test_client.py +++ b/gateway-api/src/gateway_api/sds/test_client.py @@ -9,6 +9,7 @@ from stubs.sds.stub import SdsFhirApiStub from gateway_api.common.error import SdsRequestFailedError +from gateway_api.conftest import NewEnvVars from gateway_api.get_structured_record import ACCESS_RECORD_STRUCTURED_INTERACTION_ID from gateway_api.sds import ( SdsClient, @@ -130,17 +131,15 @@ def test_sds_client_sends_correct_headers( :param stub: SDS stub fixture. :param mock_requests_get: Capture fixture for request details. """ - client = SdsClient(base_url=SdsClient.SANDBOX_URL) - - correlation_id = "test-correlation-123" - client.get_org_details(ods_code="PROVIDER", correlation_id=correlation_id) + with NewEnvVars({"SDS_API_KEY": "example_api_key"}): + client = SdsClient(base_url=SdsClient.SANDBOX_URL) - # Check that the headers were - assert stub.get_headers["X-Correlation-Id"] == correlation_id + correlation_id = "test-correlation-123" + client.get_org_details(ods_code="PROVIDER", correlation_id=correlation_id) - # In future when _get_api_key calls AWS secrets, this will break. - # That's a good thing, because we'll want to mock that call. - assert stub.get_headers["apikey"] == "test_api_key_DO_NOT_REPLACE_HERE" + # Check that the headers were + assert stub.get_headers["X-Correlation-Id"] == correlation_id + assert stub.get_headers["apikey"] == "example_api_key" def test_sds_client_timeout_parameter( From 5bc53ce9257f8d949c95816a43399d12db26f509 Mon Sep 17 00:00:00 2001 From: Ian Robinson <267046044+ian-robinson-35@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:12:45 +0000 Subject: [PATCH 4/7] Add tests --- gateway-api/src/gateway_api/sds/__init__.py | 7 ++---- gateway-api/src/gateway_api/sds/client.py | 1 + .../src/gateway_api/sds/test_client.py | 25 ++++++++++++++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/gateway-api/src/gateway_api/sds/__init__.py b/gateway-api/src/gateway_api/sds/__init__.py index 8f6e5ec0..bfbe89ef 100644 --- a/gateway-api/src/gateway_api/sds/__init__.py +++ b/gateway-api/src/gateway_api/sds/__init__.py @@ -1,7 +1,4 @@ -from gateway_api.sds.client import SdsClient +from gateway_api.sds.client import SdsClient, get from gateway_api.sds.search_results import SdsSearchResults -__all__ = [ - "SdsClient", - "SdsSearchResults", -] +__all__ = ["SdsClient", "SdsSearchResults", "get"] diff --git a/gateway-api/src/gateway_api/sds/client.py b/gateway-api/src/gateway_api/sds/client.py index 2ce38289..0d666876 100644 --- a/gateway-api/src/gateway_api/sds/client.py +++ b/gateway-api/src/gateway_api/sds/client.py @@ -34,6 +34,7 @@ def get( if not STUB_SDS: return external_sds_get(url, headers=headers, params=params, timeout=timeout) else: + print("IanR: Calling stub ", SdsFhirApiStub().get) return SdsFhirApiStub().get( url, headers=headers, params=params, timeout=timeout ) diff --git a/gateway-api/src/gateway_api/sds/test_client.py b/gateway-api/src/gateway_api/sds/test_client.py index 4ad86371..9c54d895 100644 --- a/gateway-api/src/gateway_api/sds/test_client.py +++ b/gateway-api/src/gateway_api/sds/test_client.py @@ -4,6 +4,8 @@ from __future__ import annotations +from unittest.mock import Mock, patch + import pytest from fhir.constants import FHIRSystem from stubs.sds.stub import SdsFhirApiStub @@ -11,10 +13,7 @@ from gateway_api.common.error import SdsRequestFailedError from gateway_api.conftest import NewEnvVars from gateway_api.get_structured_record import ACCESS_RECORD_STRUCTURED_INTERACTION_ID -from gateway_api.sds import ( - SdsClient, - SdsSearchResults, -) +from gateway_api.sds import SdsClient, SdsSearchResults, get @pytest.fixture @@ -416,3 +415,21 @@ def test_sds_client_no_endpoint_bundle_entries_returns_none_endpoint( assert result.asid == "222222222222" assert result.endpoint is None + + +@patch("gateway_api.sds.client.SdsFhirApiStub") +@patch("gateway_api.sds.client.external_sds_get") +def test_get_with_stub(mock_external_get: Mock, mock_stub: Mock) -> None: + with NewEnvVars({"STUB_SDS": "true"}): + get("https://example.com/", headers={}, params={}, timeout=10) + assert mock_stub.return_value.get.called + assert not mock_external_get.called + + +@patch("gateway_api.sds.client.SdsFhirApiStub") +@patch("gateway_api.sds.client.external_sds_get") +def test_get_without_stub(mock_external_get: Mock, mock_stub: Mock) -> None: + with NewEnvVars({"STUB_SDS": "false"}): + get("https://example.com/", headers={}, params={}, timeout=10) + assert mock_external_get.called + assert not mock_stub.return_value.get.called From 8896249bbb92f685220bc85b5d2f20e493e6798b Mon Sep 17 00:00:00 2001 From: Ian Robinson <267046044+ian-robinson-35@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:14:41 +0000 Subject: [PATCH 5/7] Remove debug --- gateway-api/src/gateway_api/sds/client.py | 1 - 1 file changed, 1 deletion(-) diff --git a/gateway-api/src/gateway_api/sds/client.py b/gateway-api/src/gateway_api/sds/client.py index 0d666876..2ce38289 100644 --- a/gateway-api/src/gateway_api/sds/client.py +++ b/gateway-api/src/gateway_api/sds/client.py @@ -34,7 +34,6 @@ def get( if not STUB_SDS: return external_sds_get(url, headers=headers, params=params, timeout=timeout) else: - print("IanR: Calling stub ", SdsFhirApiStub().get) return SdsFhirApiStub().get( url, headers=headers, params=params, timeout=timeout ) From b88ba0000fa0bd187908d67b47a5205f85c89f67 Mon Sep 17 00:00:00 2001 From: Ian Robinson <267046044+ian-robinson-35@users.noreply.github.com> Date: Tue, 28 Apr 2026 13:01:19 +0000 Subject: [PATCH 6/7] Added tests --- .../src/gateway_api/sds/test_client.py | 15 ++-- gateway-api/src/gateway_api/test_app.py | 31 +++++++- .../src/gateway_api/test_controller.py | 72 ++++++------------- 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/gateway-api/src/gateway_api/sds/test_client.py b/gateway-api/src/gateway_api/sds/test_client.py index 771107da..99e3d187 100644 --- a/gateway-api/src/gateway_api/sds/test_client.py +++ b/gateway-api/src/gateway_api/sds/test_client.py @@ -122,15 +122,14 @@ def test_sds_client_sends_correct_headers(stub: SdsFhirApiStub) -> None: :param stub: SDS stub fixture. :param mock_requests_get: Capture fixture for request details. """ - with ScopedEnvVars({"SDS_api_key": "example_api_key"}): - client = SdsClient(base_url="https://test.com", api_key="example_api_key") + client = SdsClient(base_url="https://test.com", api_key="example_api_key") - correlation_id = "test-correlation-123" - client.get_org_details(ods_code="PROVIDER", correlation_id=correlation_id) + correlation_id = "test-correlation-123" + client.get_org_details(ods_code="PROVIDER", correlation_id=correlation_id) - # Check that the headers were - assert stub.get_headers["X-Correlation-Id"] == correlation_id - assert stub.get_headers["apikey"] == "example_api_key" + # Check that the headers were + assert stub.get_headers["X-Correlation-Id"] == correlation_id + assert stub.get_headers["apikey"] == "example_api_key" def test_sds_client_timeout_parameter(stub: SdsFhirApiStub) -> None: @@ -408,7 +407,9 @@ def test_sds_client_respects_url(mocker: MockerFixture) -> None: _ = client.get_org_details(ods_code="A12345", get_endpoint=False) actual_url = mocked_get.call_args.args[0] + actual_headers = mocked_get.call_args.kwargs["headers"] assert actual_url == "https://a.different.url/base/Device" + assert actual_headers["apikey"] == "example_api_key" @patch("gateway_api.sds.client.SdsFhirApiStub") diff --git a/gateway-api/src/gateway_api/test_app.py b/gateway-api/src/gateway_api/test_app.py index 517795f6..7d112d2c 100644 --- a/gateway-api/src/gateway_api/test_app.py +++ b/gateway-api/src/gateway_api/test_app.py @@ -3,7 +3,7 @@ import json from collections.abc import Generator from copy import copy -from typing import Any +from typing import Any, cast from unittest.mock import Mock import pytest @@ -11,6 +11,7 @@ from flask.testing import FlaskClient from pytest_mock import MockerFixture +import gateway_api from gateway_api.app import ( app, configure_app, @@ -20,6 +21,10 @@ ) from gateway_api.conftest import ScopedEnvVars +PDS_URL = "http://test-pds-url" +SDS_URL = "http://test-sds-url" +SDS_API_TOKEN = "example-token" # noqa: S105 Not a real token + @pytest.fixture def client() -> Generator[FlaskClient[Flask]]: @@ -27,8 +32,9 @@ def client() -> Generator[FlaskClient[Flask]]: { "FLASK_HOST": "localhost", "FLASK_PORT": "5000", - "PDS_URL": "http://test-pds-url", - "SDS_URL": "http://test-sds-url", + "PDS_URL": PDS_URL, + "SDS_URL": SDS_URL, + "SDS_API_TOKEN": SDS_API_TOKEN, } ): configure_app(app) @@ -120,6 +126,18 @@ def test_valid_get_structured_record_request_returns_expected_bundle( actual_bundle = get_structured_record_response.get_json() assert actual_bundle == valid_simple_response_payload + @pytest.mark.usefixtures("mock_controller_constructor") + def test_valid_get_structured_record_request_calls_controller_correctly( + self, + get_structured_record_response: Flask, + ) -> None: + get_structured_record_response.get_json() + cast("Mock", gateway_api.controller.Controller.__init__).assert_called_with( + pds_base_url="http://test-pds-url", + sds_base_url="http://test-sds-url", + sds_api_key="example-token", + ) + @pytest.mark.usefixtures("mock_positive_return_value_from_controller_run") def test_valid_get_structured_record_request_returns_200( self, @@ -293,6 +311,13 @@ def mock_positive_return_value_from_controller_run( "gateway_api.controller.Controller.run", return_value=positive_response ) + @staticmethod + @pytest.fixture + def mock_controller_constructor( + mocker: MockerFixture, + ) -> None: + mocker.patch("gateway_api.controller.Controller.__init__", return_value=None) + @staticmethod @pytest.fixture def mock_raise_error_from_controller_run( diff --git a/gateway-api/src/gateway_api/test_controller.py b/gateway-api/src/gateway_api/test_controller.py index 2cf021a5..728e07ad 100644 --- a/gateway-api/src/gateway_api/test_controller.py +++ b/gateway-api/src/gateway_api/test_controller.py @@ -395,61 +395,35 @@ def test_controller_respects_pds_url( assert actual_pds_url == "https://a.different.url/base/Patient/9000000009" -def test_controller_respects_sds_url( +def test_controller_respects_sds_vars( mocker: MockerFixture, ) -> None: """ - Test that the controller uses the SDS URL provided in the constructor. + Test that the controller uses the SDS URL and API token provided in the constructor. """ - device_bundle = { - "resourceType": "Bundle", - "type": "searchset", - "total": 1, - "entry": [ - { - "fullUrl": "https://example.test/sds/Device/1", - "resource": { - "resourceType": "Device", - "identifier": [ - { - "system": "https://fhir.nhs.uk/Id/nhsSpineASID", - "value": "test-asid", - }, - { - "system": "https://fhir.nhs.uk/Id/nhsMhsPartyKey", - "value": "test-party-key", - }, - ], - }, - } - ], - } - endpoint_bundle = { - "resourceType": "Bundle", - "type": "searchset", - "total": 1, - "entry": [ - { - "fullUrl": "https://example.test/sds/Endpoint/1", - "resource": { - "resourceType": "Endpoint", - "address": "https://example.provider.org/endpoint", - }, - } - ], - } - mocked_get_sds = mocker.patch( - "gateway_api.sds.client.get", - side_effect=[ - FakeResponse(status_code=200, headers={}, _json=device_bundle), - FakeResponse(status_code=200, headers={}, _json=endpoint_bundle), - FakeResponse(status_code=200, headers={}, _json=device_bundle), - ], + provider_sds_results = SdsSearchResults( + asid="ProviderASID", endpoint="https://example.provider.org/endpoint" + ) + consumer_sds_results = SdsSearchResults( + asid="ConsumerASID", endpoint="https://example.consumer.org/endpoint" + ) + sds_results = [provider_sds_results, consumer_sds_results] + mocker.patch( + "gateway_api.sds.SdsClient.get_org_details", + side_effect=sds_results, + ) + mocked_sds_client = mocker.patch( + "gateway_api.controller.SdsClient.__init__", return_value=None ) custom_sds_url = "https://a.different.url/base" + custom_sds_api_token = "custom-sds-api-token" # noqa: S105 Not a real token - controller = create_test_controller(sds_base_url=custom_sds_url) + controller = create_test_controller( + sds_base_url=custom_sds_url, sds_api_key=custom_sds_api_token + ) controller._get_sds_details("test-ods-1", "test-ods-2") - actual_sds_url = mocked_get_sds.call_args.args[0] - assert actual_sds_url == "https://a.different.url/base/Device" + actual_sds_url = mocked_sds_client.call_args.kwargs["base_url"] + actual_sds_api_token = mocked_sds_client.call_args.kwargs["api_key"] + assert actual_sds_url == "https://a.different.url/base" + assert actual_sds_api_token == custom_sds_api_token From 9138dba0c016b49cefa7dc68dc79845745ef540e Mon Sep 17 00:00:00 2001 From: Ian Robinson <267046044+ian-robinson-35@users.noreply.github.com> Date: Tue, 28 Apr 2026 13:20:19 +0000 Subject: [PATCH 7/7] Tidy up --- gateway-api/src/gateway_api/test_app.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gateway-api/src/gateway_api/test_app.py b/gateway-api/src/gateway_api/test_app.py index 7d112d2c..f25d3eba 100644 --- a/gateway-api/src/gateway_api/test_app.py +++ b/gateway-api/src/gateway_api/test_app.py @@ -133,9 +133,9 @@ def test_valid_get_structured_record_request_calls_controller_correctly( ) -> None: get_structured_record_response.get_json() cast("Mock", gateway_api.controller.Controller.__init__).assert_called_with( - pds_base_url="http://test-pds-url", - sds_base_url="http://test-sds-url", - sds_api_key="example-token", + pds_base_url=PDS_URL, + sds_base_url=SDS_URL, + sds_api_key=SDS_API_TOKEN, ) @pytest.mark.usefixtures("mock_positive_return_value_from_controller_run")