From cc6d5c34b5ca3eed047fd162cec273fb23aa0754 Mon Sep 17 00:00:00 2001 From: David Hamill <109090521+davidhamill1-nhs@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:55:27 +0000 Subject: [PATCH 1/6] [GPCAPIM-275]: Remove duplicate lines. --- gateway-api/src/gateway_api/test_app.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/gateway-api/src/gateway_api/test_app.py b/gateway-api/src/gateway_api/test_app.py index fdf77815..6e469151 100644 --- a/gateway-api/src/gateway_api/test_app.py +++ b/gateway-api/src/gateway_api/test_app.py @@ -16,9 +16,6 @@ if TYPE_CHECKING: from fhir.parameters import Parameters -if TYPE_CHECKING: - from fhir.parameters import Parameters - @pytest.fixture def client() -> Generator[FlaskClient[Flask], None, None]: From 4ebe273e91c327e3a51f98c16cda92f00cdb1749 Mon Sep 17 00:00:00 2001 From: David Hamill <109090521+davidhamill1-nhs@users.noreply.github.com> Date: Thu, 5 Feb 2026 15:09:00 +0000 Subject: [PATCH 2/6] [GPCAPIM-275]: Import modules consistently. --- gateway-api/src/gateway_api/test_app.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/gateway-api/src/gateway_api/test_app.py b/gateway-api/src/gateway_api/test_app.py index 6e469151..718466fd 100644 --- a/gateway-api/src/gateway_api/test_app.py +++ b/gateway-api/src/gateway_api/test_app.py @@ -3,13 +3,15 @@ import json import os from collections.abc import Generator -from typing import TYPE_CHECKING +from datetime import datetime, timezone +from typing import TYPE_CHECKING, Any import pytest from flask import Flask from flask.testing import FlaskClient from gateway_api.app import app, get_app_host, get_app_port +from gateway_api.common.common import FlaskResponse from gateway_api.controller import Controller from gateway_api.get_structured_record.request import GetStructuredRecordRequest @@ -58,10 +60,6 @@ def test_get_structured_record_returns_200_with_bundle( valid_simple_request_payload: "Parameters", ) -> None: """Test that successful controller response is returned correctly.""" - from datetime import datetime, timezone - from typing import Any - - from gateway_api.common.common import FlaskResponse # Mock the controller to return a successful FlaskResponse with a Bundle mock_bundle_data: Any = { From 742f2fd823082f700f949fea71cdb436b01a8282 Mon Sep 17 00:00:00 2001 From: David Hamill <109090521+davidhamill1-nhs@users.noreply.github.com> Date: Thu, 5 Feb 2026 15:22:33 +0000 Subject: [PATCH 3/6] [GPCAPIM-275]: Enable other test modules to use a valid Bundle. --- gateway-api/src/gateway_api/conftest.py | 28 +++++++++++++++++++ gateway-api/src/gateway_api/test_app.py | 37 ++++--------------------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/gateway-api/src/gateway_api/conftest.py b/gateway-api/src/gateway_api/conftest.py index 05307c86..b9866638 100644 --- a/gateway-api/src/gateway_api/conftest.py +++ b/gateway-api/src/gateway_api/conftest.py @@ -1,6 +1,9 @@ """Pytest configuration and shared fixtures for gateway API tests.""" +from datetime import datetime, timezone + import pytest +from fhir.bundle import Bundle from fhir.parameters import Parameters @@ -18,3 +21,28 @@ def valid_simple_request_payload() -> Parameters: }, ], } + + +@pytest.fixture +def valid_simple_response_payload() -> Bundle: + return { + "resourceType": "Bundle", + "id": "example-patient-bundle", + "type": "collection", + "timestamp": datetime.now(timezone.utc).isoformat(), + "entry": [ + { + "fullUrl": "http://example.com/Patient/9999999999", + "resource": { + "name": [{"family": "Alice", "given": ["Johnson"], "use": "Ally"}], + "gender": "female", + "birthDate": "1990-05-15", + "resourceType": "Patient", + "id": "9999999999", + "identifier": [ + {"value": "9999999999", "system": "urn:nhs:numbers"} + ], + }, + } + ], + } diff --git a/gateway-api/src/gateway_api/test_app.py b/gateway-api/src/gateway_api/test_app.py index 718466fd..97d2f46f 100644 --- a/gateway-api/src/gateway_api/test_app.py +++ b/gateway-api/src/gateway_api/test_app.py @@ -3,10 +3,10 @@ import json import os from collections.abc import Generator -from datetime import datetime, timezone -from typing import TYPE_CHECKING, Any import pytest +from fhir.bundle import Bundle +from fhir.parameters import Parameters from flask import Flask from flask.testing import FlaskClient @@ -15,9 +15,6 @@ from gateway_api.controller import Controller from gateway_api.get_structured_record.request import GetStructuredRecordRequest -if TYPE_CHECKING: - from fhir.parameters import Parameters - @pytest.fixture def client() -> Generator[FlaskClient[Flask], None, None]: @@ -57,42 +54,18 @@ def test_get_structured_record_returns_200_with_bundle( self, client: FlaskClient[Flask], monkeypatch: pytest.MonkeyPatch, - valid_simple_request_payload: "Parameters", + valid_simple_request_payload: Parameters, + valid_simple_response_payload: Bundle, ) -> None: """Test that successful controller response is returned correctly.""" - # Mock the controller to return a successful FlaskResponse with a Bundle - mock_bundle_data: Any = { - "resourceType": "Bundle", - "id": "example-patient-bundle", - "type": "collection", - "timestamp": datetime.now(timezone.utc).isoformat(), - "entry": [ - { - "fullUrl": "http://example.com/Patient/9999999999", - "resource": { - "name": [ - {"family": "Alice", "given": ["Johnson"], "use": "Ally"} - ], - "gender": "female", - "birthDate": "1990-05-15", - "resourceType": "Patient", - "id": "9999999999", - "identifier": [ - {"value": "9999999999", "system": "urn:nhs:numbers"} - ], - }, - } - ], - } - def mock_run( self: Controller, # noqa: ARG001 request: GetStructuredRecordRequest, # noqa: ARG001 ) -> FlaskResponse: return FlaskResponse( status_code=200, - data=json.dumps(mock_bundle_data), + data=json.dumps(valid_simple_response_payload), headers={"Content-Type": "application/fhir+json"}, ) From 41437aced651a600da455bb0b6ea764fb2ccca6a Mon Sep 17 00:00:00 2001 From: David Hamill <109090521+davidhamill1-nhs@users.noreply.github.com> Date: Thu, 5 Feb 2026 16:13:24 +0000 Subject: [PATCH 4/6] [GPCAPIM-275]: Reduce mocking complexity. Move common required headers to fixture. --- gateway-api/poetry.lock | 32 ++++++-- gateway-api/pyproject.toml | 2 + gateway-api/src/gateway_api/conftest.py | 8 ++ gateway-api/src/gateway_api/test_app.py | 101 +++++++++++------------- 4 files changed, 82 insertions(+), 61 deletions(-) diff --git a/gateway-api/poetry.lock b/gateway-api/poetry.lock index 88b054f5..b4c4e471 100644 --- a/gateway-api/poetry.lock +++ b/gateway-api/poetry.lock @@ -349,7 +349,7 @@ files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {main = "platform_system == \"Windows\""} +markers = {main = "platform_system == \"Windows\" or sys_platform == \"win32\""} [[package]] name = "coverage" @@ -684,7 +684,7 @@ version = "2.3.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.10" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, @@ -1196,7 +1196,7 @@ version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, @@ -1294,7 +1294,7 @@ version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.9" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, @@ -1455,7 +1455,7 @@ version = "2.19.2" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, @@ -1486,7 +1486,7 @@ version = "8.4.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.9" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"}, {file = "pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01"}, @@ -1582,6 +1582,24 @@ pytest = ">=7.0.0" [package.extras] test = ["black (>=22.1.0)", "flake8 (>=4.0.1)", "pre-commit (>=2.17.0)", "tox (>=3.24.5)"] +[[package]] +name = "pytest-mock" +version = "3.15.1" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.9" +groups = ["main", "dev"] +files = [ + {file = "pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d"}, + {file = "pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + [[package]] name = "pytest-subtests" version = "0.14.2" @@ -2360,4 +2378,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.1" python-versions = ">3.13,<4.0.0" -content-hash = "a452bd22e2386a3ff58b4c7a5ac2cb571de9e3d49a4fbc161ffd3aafa2a7bf44" +content-hash = "9646e1adfb86cc4e07b149bc1a93f1e32921f0cd50c57603cdb6fe907092ce7a" diff --git a/gateway-api/pyproject.toml b/gateway-api/pyproject.toml index 748ebd4f..b95d627c 100644 --- a/gateway-api/pyproject.toml +++ b/gateway-api/pyproject.toml @@ -13,6 +13,7 @@ clinical-data-common = { git = "https://github.com/NHSDigital/clinical-data-comm flask = "^3.1.2" types-flask = "^1.1.6" requests = "^2.32.5" +pytest-mock = "^3.15.1" [tool.poetry] packages = [{include = "gateway_api", from = "src"}, @@ -55,6 +56,7 @@ dev = [ "schemathesis>=4.4.1", "types-requests (>=2.32.4.20250913,<3.0.0.0)", "types-pyyaml (>=6.0.12.20250915,<7.0.0.0)", + "pytest-mock (>=3.15.1,<4.0.0)", ] [tool.mypy] diff --git a/gateway-api/src/gateway_api/conftest.py b/gateway-api/src/gateway_api/conftest.py index b9866638..d9db3b59 100644 --- a/gateway-api/src/gateway_api/conftest.py +++ b/gateway-api/src/gateway_api/conftest.py @@ -46,3 +46,11 @@ def valid_simple_response_payload() -> Bundle: } ], } + + +@pytest.fixture +def valid_headers() -> dict[str, str]: + return { + "Ssp-TraceID": "test-trace-id", + "ODS-from": "test-ods", + } diff --git a/gateway-api/src/gateway_api/test_app.py b/gateway-api/src/gateway_api/test_app.py index 97d2f46f..34b5e042 100644 --- a/gateway-api/src/gateway_api/test_app.py +++ b/gateway-api/src/gateway_api/test_app.py @@ -3,17 +3,17 @@ import json import os from collections.abc import Generator +from copy import copy import pytest from fhir.bundle import Bundle from fhir.parameters import Parameters from flask import Flask from flask.testing import FlaskClient +from pytest_mock import MockerFixture from gateway_api.app import app, get_app_host, get_app_port from gateway_api.common.common import FlaskResponse -from gateway_api.controller import Controller -from gateway_api.get_structured_record.request import GetStructuredRecordRequest @pytest.fixture @@ -53,25 +53,19 @@ class TestGetStructuredRecord: def test_get_structured_record_returns_200_with_bundle( self, client: FlaskClient[Flask], - monkeypatch: pytest.MonkeyPatch, + mocker: MockerFixture, valid_simple_request_payload: Parameters, valid_simple_response_payload: Bundle, ) -> None: """Test that successful controller response is returned correctly.""" - def mock_run( - self: Controller, # noqa: ARG001 - request: GetStructuredRecordRequest, # noqa: ARG001 - ) -> FlaskResponse: - return FlaskResponse( - status_code=200, - data=json.dumps(valid_simple_response_payload), - headers={"Content-Type": "application/fhir+json"}, - ) - - monkeypatch.setattr( - "gateway_api.controller.Controller.run", - mock_run, + postive_response = FlaskResponse( + status_code=200, + data=json.dumps(valid_simple_response_payload), + headers={"Content-Type": "application/fhir+json"}, + ) + mocker.patch( + "gateway_api.controller.Controller.run", return_value=postive_response ) response = client.post( @@ -96,73 +90,72 @@ def mock_run( assert data["entry"][0]["resource"]["id"] == "9999999999" assert data["entry"][0]["resource"]["identifier"][0]["value"] == "9999999999" - def test_get_structured_record_handles_exception( + def test_get_structured_record_returns_500_when_an_uncaught_exception_is_raised( self, client: FlaskClient[Flask], - monkeypatch: pytest.MonkeyPatch, + mocker: MockerFixture, valid_simple_request_payload: "Parameters", + valid_headers: dict[str, str], ) -> None: - """ - Test that exceptions during controller execution are caught and return 500. - """ - - # This is mocking the run method of the Controller - # and therefore self is a Controller - def mock_run_with_exception( - self: Controller, # noqa: ARG001 - request: GetStructuredRecordRequest, # noqa: ARG001 - ) -> None: - raise ValueError("Test exception") - - monkeypatch.setattr( - "gateway_api.controller.Controller.run", - mock_run_with_exception, + internal_error = ValueError("Test exception") + mocker.patch( + "gateway_api.controller.Controller.run", side_effect=internal_error ) response = client.post( "/patient/$gpc.getstructuredrecord", json=valid_simple_request_payload, - headers={ - "Ssp-TraceID": "test-trace-id", - "ODS-from": "test-ods", - }, + headers=valid_headers, ) assert response.status_code == 500 - def test_get_structured_record_handles_request_validation_error( + @pytest.mark.parametrize( + ("missing_header_key", "expected_message"), + [ + pytest.param( + "ODS-from", + b'Missing or empty required header "ODS-from"', + id="missing ODS code", + ), + pytest.param( + "Ssp-TraceID", + b'Missing or empty required header "Ssp-TraceID"', + id="missing trace id", + ), + ], + ) + def test_get_structured_record_request_returns_400_when_required_header_missing( self, client: FlaskClient[Flask], valid_simple_request_payload: "Parameters", + valid_headers: dict[str, str], + missing_header_key: str, + expected_message: bytes, ) -> None: """Test that RequestValidationError returns 400 with error message.""" - # Create a request missing the required ODS-from header + invalid_headers = copy(valid_headers) + del invalid_headers[missing_header_key] + response = client.post( "/patient/$gpc.getstructuredrecord", json=valid_simple_request_payload, - headers={ - "Ssp-TraceID": "test-trace-id", - # Missing "ODS-from" header to trigger RequestValidationError - }, + headers=invalid_headers, ) assert response.status_code == 400 assert "text/plain" in response.content_type - assert b'Missing or empty required header "ODS-from"' in response.data + assert expected_message in response.data - def test_get_structured_record_handles_unexpected_exception_during_init( - self, - client: FlaskClient[Flask], + def test_get_structured_record_handles_invalid_json_data( + self, client: FlaskClient[Flask], valid_headers: dict[str, str] ) -> None: """Test that unexpected exceptions during request init return 500.""" - # Send invalid JSON to trigger an exception during request processing + invalid_json = "invalid json data" + response = client.post( "/patient/$gpc.getstructuredrecord", - data="invalid json data", - headers={ - "Ssp-TraceID": "test-trace-id", - "ODS-from": "test-ods", - "Content-Type": "application/fhir+json", - }, + data=invalid_json, + headers=valid_headers, ) assert response.status_code == 500 From dd8c3180c25a0a400e1d0a3898a1bc06ec833163 Mon Sep 17 00:00:00 2001 From: David Hamill <109090521+davidhamill1-nhs@users.noreply.github.com> Date: Thu, 5 Feb 2026 17:06:24 +0000 Subject: [PATCH 5/6] [GPCAPIM-275]: Resolve spurious Sonar issue --- gateway-api/src/gateway_api/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gateway-api/src/gateway_api/conftest.py b/gateway-api/src/gateway_api/conftest.py index d9db3b59..c7a16d40 100644 --- a/gateway-api/src/gateway_api/conftest.py +++ b/gateway-api/src/gateway_api/conftest.py @@ -32,7 +32,7 @@ def valid_simple_response_payload() -> Bundle: "timestamp": datetime.now(timezone.utc).isoformat(), "entry": [ { - "fullUrl": "http://example.com/Patient/9999999999", + "fullUrl": "https://example.com/Patient/9999999999", "resource": { "name": [{"family": "Alice", "given": ["Johnson"], "use": "Ally"}], "gender": "female", From 4f1534da5520886bd1bad5541079c8106040fb25 Mon Sep 17 00:00:00 2001 From: David Hamill <109090521+davidhamill1-nhs@users.noreply.github.com> Date: Thu, 5 Feb 2026 17:57:17 +0000 Subject: [PATCH 6/6] [GPCAPIM-275]: Use single assertion in unit tests --- gateway-api/src/gateway_api/test_app.py | 166 +++++++++++++++--------- 1 file changed, 107 insertions(+), 59 deletions(-) diff --git a/gateway-api/src/gateway_api/test_app.py b/gateway-api/src/gateway_api/test_app.py index 34b5e042..9c4a2dcf 100644 --- a/gateway-api/src/gateway_api/test_app.py +++ b/gateway-api/src/gateway_api/test_app.py @@ -50,64 +50,53 @@ def test_get_app_port_raises_runtime_error_if_port_not_set(self) -> None: class TestGetStructuredRecord: - def test_get_structured_record_returns_200_with_bundle( + @pytest.mark.usefixtures("mock_positive_return_value_from_controller_run") + def test_valid_get_structured_record_request_returns_bundle( self, - client: FlaskClient[Flask], - mocker: MockerFixture, - valid_simple_request_payload: Parameters, - valid_simple_response_payload: Bundle, + get_structured_record_response: Flask, ) -> None: - """Test that successful controller response is returned correctly.""" - - postive_response = FlaskResponse( - status_code=200, - data=json.dumps(valid_simple_response_payload), - headers={"Content-Type": "application/fhir+json"}, - ) - mocker.patch( - "gateway_api.controller.Controller.run", return_value=postive_response - ) - - response = client.post( - "/patient/$gpc.getstructuredrecord", - json=valid_simple_request_payload, - headers={ - "Ssp-TraceID": "test-trace-id", - "ODS-from": "test-ods", - }, - ) - - assert response.status_code == 200 - data = response.get_json() - assert isinstance(data, dict) - assert data.get("resourceType") == "Bundle" - assert data.get("id") == "example-patient-bundle" - assert data.get("type") == "collection" - assert "entry" in data - assert isinstance(data["entry"], list) - assert len(data["entry"]) > 0 - assert data["entry"][0]["resource"]["resourceType"] == "Patient" - assert data["entry"][0]["resource"]["id"] == "9999999999" - assert data["entry"][0]["resource"]["identifier"][0]["value"] == "9999999999" + expected_body_wihtout_timestamp = { + "resourceType": "Bundle", + "id": "example-patient-bundle", + "type": "collection", + "entry": [ + { + "fullUrl": "https://example.com/Patient/9999999999", + "resource": { + "name": [ + {"family": "Alice", "given": ["Johnson"], "use": "Ally"} + ], + "gender": "female", + "birthDate": "1990-05-15", + "resourceType": "Patient", + "id": "9999999999", + "identifier": [ + {"value": "9999999999", "system": "urn:nhs:numbers"} + ], + }, + } + ], + } + + actual_body_without_timestamp = get_structured_record_response.get_json() + del actual_body_without_timestamp["timestamp"] + + assert actual_body_without_timestamp == expected_body_wihtout_timestamp + + @pytest.mark.usefixtures("mock_positive_return_value_from_controller_run") + def test_valid_get_structured_record_request_returns_200( + self, + get_structured_record_response: Flask, + ) -> None: + assert get_structured_record_response.status_code == 200 + @pytest.mark.usefixtures("mock_raise_error_from_controller_run") def test_get_structured_record_returns_500_when_an_uncaught_exception_is_raised( self, - client: FlaskClient[Flask], - mocker: MockerFixture, - valid_simple_request_payload: "Parameters", - valid_headers: dict[str, str], + get_structured_record_response: Flask, ) -> None: - internal_error = ValueError("Test exception") - mocker.patch( - "gateway_api.controller.Controller.run", side_effect=internal_error - ) - - response = client.post( - "/patient/$gpc.getstructuredrecord", - json=valid_simple_request_payload, - headers=valid_headers, - ) - assert response.status_code == 500 + actual_status_code = get_structured_record_response.status_code + assert actual_status_code == 500 @pytest.mark.parametrize( ("missing_header_key", "expected_message"), @@ -132,7 +121,6 @@ def test_get_structured_record_request_returns_400_when_required_header_missing( missing_header_key: str, expected_message: bytes, ) -> None: - """Test that RequestValidationError returns 400 with error message.""" invalid_headers = copy(valid_headers) del invalid_headers[missing_header_key] @@ -146,10 +134,47 @@ def test_get_structured_record_request_returns_400_when_required_header_missing( assert "text/plain" in response.content_type assert expected_message in response.data - def test_get_structured_record_handles_invalid_json_data( - self, client: FlaskClient[Flask], valid_headers: dict[str, str] + def test_get_structured_record_returns_500_when_invalid_json_sent( + self, get_structured_record_response_using_invalid_json_body: Flask + ) -> None: + assert get_structured_record_response_using_invalid_json_body.status_code == 500 + + def test_get_structured_record_returns_content_type_textplain_for_invalid_json_sent( + self, get_structured_record_response_using_invalid_json_body: Flask ) -> None: - """Test that unexpected exceptions during request init return 500.""" + assert ( + "text/plain" + in get_structured_record_response_using_invalid_json_body.content_type + ) + + def test_get_structured_record_returns_intenral_server_error_when_invalid_json_sent( + self, get_structured_record_response_using_invalid_json_body: Flask + ) -> None: + assert ( + b"Internal Server Error:" + in get_structured_record_response_using_invalid_json_body.data + ) + + @staticmethod + @pytest.fixture + def get_structured_record_response( + client: FlaskClient[Flask], + valid_headers: dict[str, str], + valid_simple_request_payload: Parameters, + ) -> Flask: + response = client.post( + "/patient/$gpc.getstructuredrecord", + json=valid_simple_request_payload, + headers=valid_headers, + ) + return response + + @staticmethod + @pytest.fixture + def get_structured_record_response_using_invalid_json_body( + client: FlaskClient[Flask], + valid_headers: dict[str, str], + ) -> Flask: invalid_json = "invalid json data" response = client.post( @@ -157,10 +182,33 @@ def test_get_structured_record_handles_invalid_json_data( data=invalid_json, headers=valid_headers, ) + return response - assert response.status_code == 500 - assert "text/plain" in response.content_type - assert b"Internal Server Error:" in response.data + @staticmethod + @pytest.fixture + def mock_positive_return_value_from_controller_run( + mocker: MockerFixture, + valid_headers: dict[str, str], + valid_simple_response_payload: Bundle, + ) -> None: + postive_response = FlaskResponse( + status_code=200, + data=json.dumps(valid_simple_response_payload), + headers=valid_headers, + ) + mocker.patch( + "gateway_api.controller.Controller.run", return_value=postive_response + ) + + @staticmethod + @pytest.fixture + def mock_raise_error_from_controller_run( + mocker: MockerFixture, + ) -> None: + internal_error = ValueError("Test exception") + mocker.patch( + "gateway_api.controller.Controller.run", side_effect=internal_error + ) class TestHealthCheck: