Skip to content

Commit d19b7d0

Browse files
committed
refactor: improve initialization of WebserverRpcSideEffects and update test fixtures for clarity
1 parent 0d91088 commit d19b7d0

File tree

4 files changed

+68
-87
lines changed

4 files changed

+68
-87
lines changed

packages/pytest-simcore/src/pytest_simcore/helpers/webserver_rpc_server.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@
2626
class WebserverRpcSideEffects:
2727
# pylint: disable=no-self-use
2828

29-
def __init__(
30-
self,
31-
project_job_rpc_get: ProjectJobRpcGet = ProjectJobRpcGet.model_validate(
32-
ProjectJobRpcGet.model_json_schema()["examples"][0]
33-
),
34-
):
35-
self.project_job_rpc_get = project_job_rpc_get
29+
def __init__(self, project_job_rpc_get: ProjectJobRpcGet | None = None):
30+
self.project_job_rpc_get = (
31+
project_job_rpc_get
32+
or ProjectJobRpcGet.model_validate(
33+
ProjectJobRpcGet.model_json_schema()["examples"][0]
34+
)
35+
)
3636

3737
@validate_call(config={"arbitrary_types_allowed": True})
3838
async def mark_project_as_job(

services/api-server/tests/unit/api_functions/test_api_routers_functions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ async def test_run_project_function(
413413
auth: httpx.BasicAuth,
414414
user_identity: Identity,
415415
user_email: EmailStr,
416-
job_links: JobLinks,
416+
fake_job_links: JobLinks,
417417
mocked_webserver_rest_api_base: respx.MockRouter,
418418
mocked_directorv2_rest_api_base: respx.MockRouter,
419419
create_respx_mock_from_capture,
@@ -499,7 +499,7 @@ def _default_side_effect(
499499
function=fake_registered_project_function,
500500
pre_registered_function_job_data=pre_registered_function_job_data,
501501
pricing_spec=None,
502-
job_links=job_links,
502+
job_links=fake_job_links,
503503
x_simcore_parent_project_uuid=None,
504504
x_simcore_parent_node_id=None,
505505
)

services/api-server/tests/unit/conftest.py

Lines changed: 58 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from fastapi import FastAPI, status
2525
from fastapi.encoders import jsonable_encoder
2626
from httpx import ASGITransport, Request, Response
27+
from models_library.api_schemas_catalog import CATALOG_RPC_NAMESPACE
2728
from models_library.api_schemas_long_running_tasks.tasks import (
2829
TaskGet,
2930
TaskProgress,
@@ -42,6 +43,7 @@
4243
from models_library.products import ProductName
4344
from models_library.projects import ProjectID
4445
from models_library.projects_nodes_io import BaseFileLink, SimcoreS3FileID
46+
from models_library.rabbitmq_basic_types import RPCMethodName, RPCNamespace
4547
from models_library.rpc.webserver.projects import ProjectJobRpcGet
4648
from models_library.users import UserID
4749
from moto.server import ThreadedMotoServer
@@ -57,6 +59,7 @@
5759
from pytest_simcore.simcore_webserver_projects_rest_api import GET_PROJECT
5860
from requests.auth import HTTPBasicAuth
5961
from respx import MockRouter
62+
from servicelib.rabbitmq._client_rpc import RabbitMQRPCClient
6063
from simcore_service_api_server.api.dependencies.authentication import Identity
6164
from simcore_service_api_server.core.application import create_app
6265
from simcore_service_api_server.core.settings import ApplicationSettings
@@ -254,31 +257,71 @@ def mocked_s3_server_url() -> Iterator[HttpUrl]:
254257

255258

256259
@pytest.fixture
257-
def mocked_app_dependencies(app: FastAPI, mocker: MockerFixture) -> Iterator[None]:
260+
def mocked_rabbit_rpc_client(mocker: MockerFixture) -> MockType:
261+
"""This fixture mocks the RabbitMQRPCClient.request method which is used
262+
in all RPC clients in the api-server, regardeless of the namespace.
263+
"""
264+
265+
async def _request(
266+
namespace: RPCNamespace,
267+
method_name: RPCMethodName,
268+
**kwargs,
269+
) -> Any:
270+
271+
kwargs.pop("timeout_s", None) # remove timeout from kwargs
272+
273+
# NOTE: we could switch to different namespaces
274+
if namespace == CATALOG_RPC_NAMESPACE:
275+
catalog_side_effect = CatalogRpcSideEffects()
276+
return await getattr(catalog_side_effect, method_name)(
277+
mocker.MagicMock(), **kwargs
278+
)
279+
280+
# if not namespace == WEBSERVER_RPC_NAMESPACE
281+
webserver_side_effect = WebserverRpcSideEffects()
282+
return await getattr(webserver_side_effect, method_name)(
283+
mocker.MagicMock(), **kwargs
284+
)
285+
286+
pytest.fail(f"Unexpected namespace {namespace} and method {method_name}")
287+
288+
# NOTE: mocks RabbitMQRPCClient.request(...)
289+
mock = mocker.MagicMock(spec=RabbitMQRPCClient)
290+
mock.request.side_effect = _request
291+
292+
return mock
293+
294+
295+
@pytest.fixture
296+
def mocked_app_dependencies(
297+
app: FastAPI, mocker: MockerFixture, mocked_rabbit_rpc_client: MockType
298+
) -> Iterator[None]:
258299
"""
259300
Mocks some dependency overrides for the FastAPI app.
260301
"""
261302
assert app.state.settings.API_SERVER_RABBITMQ is None
262-
from servicelib.rabbitmq import RabbitMQRPCClient
263303
from simcore_service_api_server.api.dependencies.rabbitmq import (
264304
get_rabbitmq_rpc_client,
265305
)
266306
from simcore_service_api_server.api.dependencies.webserver_rpc import (
267307
get_wb_api_rpc_client,
268308
)
269309

310+
# Overrides Depends[get_rabbitmq_rpc_client]
270311
def _get_rabbitmq_rpc_client_override():
271-
return mocker.MagicMock()
312+
return mocked_rabbit_rpc_client
272313

314+
app.dependency_overrides[get_rabbitmq_rpc_client] = (
315+
_get_rabbitmq_rpc_client_override
316+
)
317+
318+
# Overrides Depends[get_wb_api_rpc_client]
273319
async def _get_wb_api_rpc_client_override():
274320
from simcore_service_api_server.services_rpc import wb_api_server
275321

276-
wb_api_server.setup(app, mocker.MagicMock(spec=RabbitMQRPCClient))
322+
wb_api_server.setup(app, rabbitmq_rpc_client=mocked_rabbit_rpc_client)
277323
return WbApiRpcClient.get_from_app_state(app)
278324

279-
app.dependency_overrides[get_rabbitmq_rpc_client] = (
280-
_get_rabbitmq_rpc_client_override
281-
)
282325
app.dependency_overrides[get_wb_api_rpc_client] = _get_wb_api_rpc_client_override
283326

284327
yield
@@ -562,51 +605,30 @@ def mocked_catalog_rest_api_base(
562605

563606

564607
@pytest.fixture
565-
def project_job_rpc_get() -> ProjectJobRpcGet:
608+
def fake_project_job_rpc_get() -> ProjectJobRpcGet:
566609
example = ProjectJobRpcGet.model_json_schema()["examples"][0]
567610
return ProjectJobRpcGet.model_validate(example)
568611

569612

570613
@pytest.fixture
571-
def job_links() -> JobLinks:
614+
def fake_job_links() -> JobLinks:
572615
example = JobLinks.model_json_schema()["examples"][0]
573616
return JobLinks.model_validate(example)
574617

575618

576619
@pytest.fixture
577620
def mocked_webserver_rpc_api(
578621
mocked_app_dependencies: None,
579-
mocker: MockerFixture,
580-
project_job_rpc_get: ProjectJobRpcGet,
622+
mocked_rabbit_rpc_client: MockType,
581623
) -> dict[str, MockType]:
582624
"""
583-
Mocks the webserver's simcore service RPC API for testing purposes.
584-
"""
585-
from servicelib.rabbitmq.rpc_interfaces.webserver import (
586-
projects as projects_rpc, # keep import here
587-
)
588-
589-
side_effects = WebserverRpcSideEffects(project_job_rpc_get=project_job_rpc_get)
625+
In reality this fixture will mock the underlying RabbitMQRPCClient.request method
626+
used in the webserver's RPC client which fakes the webserver's RPC API response for testing purposes.
590627
628+
NOTE: the responses are defined in the mocked_rabbit_rpc_client fixture
629+
"""
591630
return {
592-
"mark_project_as_job": mocker.patch.object(
593-
projects_rpc,
594-
"mark_project_as_job",
595-
autospec=True,
596-
side_effect=side_effects.mark_project_as_job,
597-
),
598-
"get_project_marked_as_job": mocker.patch.object(
599-
projects_rpc,
600-
"get_project_marked_as_job",
601-
autospec=True,
602-
side_effect=side_effects.get_project_marked_as_job,
603-
),
604-
"list_projects_marked_as_jobs": mocker.patch.object(
605-
projects_rpc,
606-
"list_projects_marked_as_jobs",
607-
autospec=True,
608-
side_effect=side_effects.list_projects_marked_as_jobs,
609-
),
631+
"mocked_rabbit_rpc_client": mocked_rabbit_rpc_client,
610632
}
611633

612634

services/api-server/tests/unit/service/conftest.py

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,14 @@
33
# pylint: disable=unused-argument
44
# pylint: disable=unused-variable
55

6-
from typing import Any
76

87
import pytest
9-
from models_library.api_schemas_catalog import CATALOG_RPC_NAMESPACE
10-
from models_library.api_schemas_webserver import WEBSERVER_RPC_NAMESPACE
118
from models_library.api_schemas_webserver.projects import ProjectCreateNew, ProjectGet
129
from models_library.products import ProductName
13-
from models_library.rabbitmq_basic_types import RPCMethodName, RPCNamespace
10+
from models_library.rpc.webserver import WEBSERVER_RPC_NAMESPACE
1411
from models_library.users import UserID
1512
from pytest_mock import MockerFixture, MockType
1613
from pytest_simcore.helpers.catalog_rpc_server import CatalogRpcSideEffects
17-
from pytest_simcore.helpers.webserver_rpc_server import WebserverRpcSideEffects
18-
from servicelib.rabbitmq._client_rpc import RabbitMQRPCClient
1914
from simcore_service_api_server._service_jobs import JobService
2015
from simcore_service_api_server._service_programs import ProgramService
2116
from simcore_service_api_server._service_solvers import SolverService
@@ -33,42 +28,6 @@ async def catalog_rpc_side_effect():
3328
return CatalogRpcSideEffects()
3429

3530

36-
@pytest.fixture
37-
def mocked_rabbit_rpc_client(mocker: MockerFixture) -> MockType:
38-
"""This fixture mocks the RabbitMQRPCClient.request method which is used
39-
in all RPC clients in the api-server, regardeless of the namespace.
40-
"""
41-
42-
async def _request(
43-
namespace: RPCNamespace,
44-
method_name: RPCMethodName,
45-
**kwargs,
46-
) -> Any:
47-
48-
kwargs.pop("timeout_s", None) # remove timeout from kwargs
49-
50-
# NOTE: we could switch to different namespaces
51-
if namespace == WEBSERVER_RPC_NAMESPACE:
52-
webserver_side_effect = WebserverRpcSideEffects()
53-
return await getattr(webserver_side_effect, method_name)(
54-
mocker.MagicMock(), **kwargs
55-
)
56-
57-
if namespace == CATALOG_RPC_NAMESPACE:
58-
catalog_side_effect = CatalogRpcSideEffects()
59-
return await getattr(catalog_side_effect, method_name)(
60-
mocker.MagicMock(), **kwargs
61-
)
62-
63-
pytest.fail(f"Unexpected namespace {namespace} and method {method_name}")
64-
65-
# NOTE: mocks RabbitMQRPCClient.request(...)
66-
mock = mocker.MagicMock(spec=RabbitMQRPCClient)
67-
mock.request.side_effect = _request
68-
69-
return mock
70-
71-
7231
@pytest.fixture
7332
def wb_api_rpc_client(
7433
mocked_rabbit_rpc_client: MockType,

0 commit comments

Comments
 (0)