Skip to content

Commit 03799a8

Browse files
committed
Added test for backend endpoint to check for existence of multigrid controller
1 parent 239d7e9 commit 03799a8

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
from typing import Literal
2+
from unittest import mock
3+
from unittest.mock import AsyncMock, MagicMock
4+
5+
from fastapi import FastAPI
6+
from fastapi.testclient import TestClient
7+
from pytest_mock import MockerFixture
8+
9+
from murfey.server.api.auth import validate_frontend_session_access, validate_token
10+
from murfey.server.api.instrument import router as backend_router
11+
from murfey.server.murfey_db import murfey_db_session
12+
from murfey.util.api import url_path_for
13+
14+
15+
def mock_aiohttp_clientsession(
16+
mocker: MockerFixture,
17+
method: Literal["get", "post", "delete"] = "get",
18+
json_data={},
19+
status=200,
20+
):
21+
"""
22+
Helper function to patch a aiohttp.ClientSession GET request. This returns a
23+
mocked async context manager with a mocked response that, in turn, returns
24+
the given JSON data and status.
25+
26+
Returns the mocked ClientSession, which can then be inspected to assert that
27+
the expected calls were made.
28+
"""
29+
30+
# Mock out the async response
31+
mock_response = MagicMock()
32+
mock_response.json = AsyncMock(return_value=json_data)
33+
mock_response.status = status
34+
35+
# Mock out the context manager returned by clientsession.get()
36+
mock_context_manager = MagicMock()
37+
mock_context_manager.__aenter__ = AsyncMock(return_value=mock_response)
38+
mock_context_manager.__aexit__ = AsyncMock(return_value=None)
39+
40+
# Mock the client session
41+
mock_clientsession = MagicMock()
42+
mock_clientsession.__aenter__ = AsyncMock(return_value=mock_clientsession)
43+
mock_clientsession.__aexit__ = AsyncMock(return_value=None)
44+
45+
# Assign the context manager to the request method being tested
46+
getattr(mock_clientsession, method.lower()).return_value = mock_context_manager
47+
48+
# Patch 'aiohttp.ClientSession' to return the mocked client session
49+
mocker.patch("aiohttp.ClientSession", return_value=mock_clientsession)
50+
51+
return mock_clientsession, mock_response
52+
53+
54+
def test_check_multigrid_controller_exists(mocker: MockerFixture):
55+
# Set up the objects to mock
56+
instrument_name = "test"
57+
session_id = 1
58+
instrment_server_url = "https://murfey.instrument-server.test"
59+
60+
# Override the database session generator
61+
mock_session = MagicMock()
62+
mock_session.instrument_name = instrument_name
63+
mock_query_result = MagicMock()
64+
mock_query_result.one.return_value = mock_session
65+
mock_db_session = MagicMock()
66+
mock_db_session.exec.return_value = mock_query_result
67+
68+
def mock_get_db_session():
69+
yield mock_db_session
70+
71+
# Mock the machine config
72+
mock_machine_config = MagicMock()
73+
mock_machine_config.instrument_server_url = instrment_server_url
74+
mock_get_machine_config = mocker.patch(
75+
"murfey.server.api.instrument.get_machine_config"
76+
)
77+
mock_get_machine_config.return_value = {
78+
instrument_name: mock_machine_config,
79+
}
80+
81+
# Mock the instrument server tokens dictionary
82+
mock_tokens = mocker.patch(
83+
"murfey.server.api.instrument.instrument_server_tokens",
84+
{session_id: {"access_token": mock.sentinel}},
85+
)
86+
87+
# Mock out the async GET request in the endpoint
88+
mock_clientsession, _ = mock_aiohttp_clientsession(
89+
mocker,
90+
method="get",
91+
json_data={"exists": True},
92+
status=200,
93+
)
94+
95+
# Set up the backend server
96+
backend_app = FastAPI()
97+
98+
# Override validation and database dependencies
99+
backend_app.dependency_overrides[validate_token] = lambda: None
100+
backend_app.dependency_overrides[validate_frontend_session_access] = (
101+
lambda: session_id
102+
)
103+
backend_app.dependency_overrides[murfey_db_session] = mock_get_db_session
104+
backend_app.include_router(backend_router)
105+
backend_server = TestClient(backend_app)
106+
107+
# Construct the URL paths for poking and sending to
108+
backend_url_path = url_path_for(
109+
"api.instrument.router",
110+
"check_multigrid_controller_exists",
111+
session_id=session_id,
112+
)
113+
client_url_path = url_path_for(
114+
"api.router",
115+
"check_multigrid_controller_exists",
116+
session_id=session_id,
117+
)
118+
119+
# Poke the backend
120+
response = backend_server.get(backend_url_path)
121+
122+
# Check that the expected calls were made
123+
mock_db_session.exec.assert_called_once()
124+
mock_get_machine_config.assert_called_once_with(instrument_name=instrument_name)
125+
mock_clientsession.get.assert_called_once_with(
126+
f"{instrment_server_url}{client_url_path}",
127+
headers={"Authorization": f"Bearer {mock_tokens[session_id]['access_token']}"},
128+
)
129+
assert response.status_code == 200
130+
assert response.json() == {"exists": True}

0 commit comments

Comments
 (0)