Skip to content

Commit c9a23fb

Browse files
committed
tests
1 parent b8b85c7 commit c9a23fb

File tree

2 files changed

+74
-98
lines changed

2 files changed

+74
-98
lines changed

services/web/server/src/simcore_service_webserver/exceptions_handlers_http_error_map.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ async def _exception_handler(
9999
def to_exceptions_handlers_map(
100100
exc_to_http_error_map: ExceptionToHttpErrorMap,
101101
) -> ExceptionHandlersMap:
102-
"""Converts { exc_type: (status, msg), ...} -> {exc_type: callable }"""
102+
"""Converts { exc_type: (status, msg), ... } -> { exc_type: callable, ... }"""
103103
exc_handlers_map: ExceptionHandlersMap = {
104104
exc_type: create_exception_handler_from_http_error(
105105
status_code=info.status_code, msg_template=info.msg_template

services/web/server/tests/unit/isolated/test_exceptions_handlers_http_error_map.py

Lines changed: 73 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
# pylint: disable=unused-variable
77

88

9+
import logging
10+
911
import pytest
1012
from aiohttp import web
1113
from aiohttp.test_utils import make_mocked_request
@@ -14,6 +16,7 @@
1416
from simcore_service_webserver.errors import WebServerBaseError
1517
from simcore_service_webserver.exceptions_handlers_base import (
1618
AsyncDynamicTryExceptContext,
19+
async_try_except_decorator,
1720
)
1821
from simcore_service_webserver.exceptions_handlers_http_error_map import (
1922
ExceptionToHttpErrorMap,
@@ -59,120 +62,93 @@ async def test_factory__create_exception_handler_from_http_error(
5962
assert response.content_type == MIMETYPE_APPLICATION_JSON
6063

6164

62-
async def test_factory__create_exception_handler_from_http_error_map(
65+
async def test_handling_different_exceptions_with_context(
6366
fake_request: web.Request,
67+
caplog: pytest.LogCaptureFixture,
6468
):
6569
exc_to_http_error_map: ExceptionToHttpErrorMap = {
66-
OneError: HttpErrorInfo(status.HTTP_400_BAD_REQUEST, "Error One mapped to 400")
70+
OneError: HttpErrorInfo(status.HTTP_400_BAD_REQUEST, "Error {code} to 400"),
71+
OtherError: HttpErrorInfo(status.HTTP_500_INTERNAL_SERVER_ERROR, "{code}"),
6772
}
68-
6973
cm = AsyncDynamicTryExceptContext(
7074
to_exceptions_handlers_map(exc_to_http_error_map), request=fake_request
7175
)
72-
async with cm:
73-
raise OneError
74-
75-
response = cm.get_response()
76-
assert response is not None
77-
assert response.status == status.HTTP_400_BAD_REQUEST
78-
assert response.reason == "Error One mapped to 400"
7976

80-
# By-passes exceptions not listed
81-
err = RuntimeError()
82-
with pytest.raises(RuntimeError) as err_info:
77+
with caplog.at_level(logging.ERROR):
78+
# handles as 4XX
8379
async with cm:
84-
raise err
85-
86-
assert cm.get_response() is None
87-
assert err_info.value == err
88-
89-
90-
# async def test__handled_exception_context_manager(fake_request: web.Request):
91-
92-
# expected_response = web.json_response({"error": {"msg": "Foo"}})
93-
94-
# async def _custom_handler(request, exception):
95-
# assert request == fake_request
96-
# assert isinstance(
97-
# exception, BaseError
98-
# ), "only BasePluginError exceptions should call this handler"
99-
# return expected_response
100-
101-
# exc_handling_ctx = _handled_exception_context_manager(
102-
# BaseError, _custom_handler, request=fake_request
103-
# )
104-
105-
# # handles any BaseError returning a response
106-
# async with exc_handling_ctx as ctx:
107-
# raise OneError
108-
# assert ctx.response == expected_response
109-
110-
# async with exc_handling_ctx as ctx:
111-
# raise OtherError
112-
# assert ctx.response == expected_response
113-
114-
# # otherwise thru
115-
# with pytest.raises(ArithmeticError):
116-
# async with exc_handling_ctx:
117-
# raise ArithmeticError
118-
119-
120-
# async def test_create_decorator_from_exception_handler(
121-
# caplog: pytest.LogCaptureFixture,
122-
# ):
123-
# # Create an SINGLE exception handler that acts as umbrella for all these exceptions
124-
# http_error_map: ExceptionToHttpErrorMap = {
125-
# OneError: HttpErrorInfo(
126-
# status.HTTP_503_SERVICE_UNAVAILABLE,
127-
# "Human readable error transmitted to the front-end",
128-
# )
129-
# }
130-
131-
# exc_handler = create_exception_handler_from_http_error_map(http_error_map)
132-
# _exc_handling_ctx = create_decorator_from_exception_handler(
133-
# exception_types=BaseError, # <--- FIXME" this is redundant because exception has been already passed in exc_handler!
134-
# exception_handler=exc_handler,
135-
# )
80+
raise OneError
81+
82+
response = cm.get_response()
83+
assert response is not None
84+
assert response.status == status.HTTP_400_BAD_REQUEST
85+
assert response.reason == exc_to_http_error_map[OneError].msg_template.format(
86+
code="WebServerBaseError.BaseError.OneError"
87+
)
88+
assert not caplog.records
89+
90+
# unhandled -> reraises
91+
err = RuntimeError()
92+
with pytest.raises(RuntimeError) as err_info:
93+
async with cm:
94+
raise err
95+
96+
assert cm.get_response() is None
97+
assert err_info.value == err
98+
99+
# handles as 5XX and logs
100+
async with cm:
101+
raise OtherError
136102

137-
# @_exc_handling_ctx
138-
# async def _rest_handler(request: web.Request) -> web.Response:
139-
# if request.query.get("raise") == "OneError":
140-
# raise OneError
141-
# if request.query.get("raise") == "ArithmeticError":
142-
# raise ArithmeticError
103+
response = cm.get_response()
104+
assert response is not None
105+
assert response.status == status.HTTP_500_INTERNAL_SERVER_ERROR
106+
assert response.reason == exc_to_http_error_map[OtherError].msg_template.format(
107+
code="WebServerBaseError.BaseError.OtherError"
108+
)
109+
assert caplog.records, "Expected 5XX troubleshooting logged as error"
110+
assert caplog.records[0].levelno == logging.ERROR
143111

144-
# return web.Response(reason="all good")
145112

146-
# with caplog.at_level(logging.ERROR):
113+
async def test_handling_different_exceptions_with_decorator(
114+
fake_request: web.Request,
115+
caplog: pytest.LogCaptureFixture,
116+
):
117+
exc_to_http_error_map: ExceptionToHttpErrorMap = {
118+
OneError: HttpErrorInfo(status.HTTP_503_SERVICE_UNAVAILABLE, "{code}"),
119+
}
147120

148-
# # emulates successful call
149-
# resp = await _rest_handler(make_mocked_request("GET", "/foo"))
150-
# assert resp.status == status.HTTP_200_OK
151-
# assert resp.reason == "all good"
121+
exc_handling_decorator = async_try_except_decorator(
122+
to_exceptions_handlers_map(exc_to_http_error_map)
123+
)
152124

153-
# assert not caplog.records
125+
@exc_handling_decorator
126+
async def _rest_handler(request: web.Request) -> web.Response:
127+
if request.query.get("raise") == "OneError":
128+
raise OneError
129+
if request.query.get("raise") == "ArithmeticError":
130+
raise ArithmeticError
131+
return web.json_response(reason="all good")
154132

155-
# # this will be passed and catched by the outermost error middleware
156-
# with pytest.raises(ArithmeticError):
157-
# await _rest_handler(
158-
# make_mocked_request("GET", "/foo?raise=ArithmeticError")
159-
# )
133+
with caplog.at_level(logging.ERROR):
160134

161-
# assert not caplog.records
135+
# emulates successful call
136+
resp = await _rest_handler(make_mocked_request("GET", "/foo"))
137+
assert resp.status == status.HTTP_200_OK
138+
assert resp.reason == "all good"
162139

163-
# # this is a 5XX will be converted to response but is logged as error as well
164-
# with pytest.raises(web.HTTPException) as exc_info:
165-
# await _rest_handler(make_mocked_request("GET", "/foo?raise=OneError"))
140+
assert not caplog.records
166141

167-
# resp = exc_info.value
168-
# assert resp.status == status.HTTP_503_SERVICE_UNAVAILABLE
169-
# assert "front-end" in resp.reason
142+
# reraised
143+
with pytest.raises(ArithmeticError):
144+
await _rest_handler(
145+
make_mocked_request("GET", "/foo?raise=ArithmeticError")
146+
)
170147

171-
# assert caplog.records, "Expected 5XX troubleshooting logged as error"
172-
# assert caplog.records[0].levelno == logging.ERROR
148+
assert not caplog.records
173149

174-
# # typically capture by last
175-
# with pytest.raises(ArithmeticError):
176-
# resp = await _rest_handler(
177-
# make_mocked_request("GET", "/foo?raise=ArithmeticError")
178-
# )
150+
# handles as 5XX and logs
151+
resp = await _rest_handler(make_mocked_request("GET", "/foo?raise=OneError"))
152+
assert resp.status == status.HTTP_503_SERVICE_UNAVAILABLE
153+
assert caplog.records, "Expected 5XX troubleshooting logged as error"
154+
assert caplog.records[0].levelno == logging.ERROR

0 commit comments

Comments
 (0)