From 1b8d446be375771c27d340d3c1a602adc0429806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20K=C3=B6tter?= Date: Fri, 20 Dec 2024 14:29:29 +0100 Subject: [PATCH] tests --- aiopenapi3/errors.py | 4 ++-- aiopenapi3/openapi.py | 6 +++--- aiopenapi3/request.py | 2 +- tests/api/v2/main.py | 12 ++++++------ tests/apiv1_test.py | 18 +++++++++++------- tests/apiv2_test.py | 28 +++++++++++++++++++--------- tests/path_test.py | 8 ++++---- 7 files changed, 46 insertions(+), 32 deletions(-) diff --git a/aiopenapi3/errors.py b/aiopenapi3/errors.py index 01b598c4..fd426c32 100644 --- a/aiopenapi3/errors.py +++ b/aiopenapi3/errors.py @@ -202,14 +202,14 @@ def __str__(self): @dataclasses.dataclass(repr=False) -class HttpClientError(HTTPStatusIndicatedError): +class HTTPClientError(HTTPStatusIndicatedError): """response code 4xx""" pass @dataclasses.dataclass(repr=False) -class HttpServerError(HTTPStatusIndicatedError): +class HTTPServerError(HTTPStatusIndicatedError): """response code 5xx""" pass diff --git a/aiopenapi3/openapi.py b/aiopenapi3/openapi.py index f2ab6cd5..c807c267 100644 --- a/aiopenapi3/openapi.py +++ b/aiopenapi3/openapi.py @@ -28,7 +28,7 @@ from . import v31 from . import log from .request import OperationIndex, HTTP_METHODS -from .errors import ReferenceResolutionError, HttpClientError, HttpServerError +from .errors import ReferenceResolutionError, HTTPClientError, HTTPServerError from .loader import Loader, NullLoader from .plugin import Plugin, Plugins from .base import RootBase, ReferenceBase, SchemaBase, OperationBase, DiscriminatorBase @@ -267,8 +267,8 @@ def __init__( """ self.raise_on_http_status: list[tuple[type[Exception], tuple[int, int]]] = [ - (HttpClientError, (400, 499)), - (HttpServerError, (500, 599)), + (HTTPClientError, (400, 499)), + (HTTPServerError, (500, 599)), ] """ Raise for http status code diff --git a/aiopenapi3/request.py b/aiopenapi3/request.py index af65d49c..1e475a7d 100644 --- a/aiopenapi3/request.py +++ b/aiopenapi3/request.py @@ -27,7 +27,7 @@ async def aclosing(thing): from .base import HTTP_METHODS, ReferenceBase from .version import __version__ -from .errors import RequestError, OperationIdDuplicationError, HttpServerError, HttpClientError +from .errors import RequestError, OperationIdDuplicationError, HTTPServerError, HTTPClientError if typing.TYPE_CHECKING: from ._types import ( diff --git a/tests/api/v2/main.py b/tests/api/v2/main.py index a43a6bc7..c0252005 100644 --- a/tests/api/v2/main.py +++ b/tests/api/v2/main.py @@ -57,9 +57,9 @@ def listPet(limit: Optional[int] = None) -> schema.Pets: @router.get("/pets/{petId}", operation_id="getPet", response_model=schema.Pet, responses={404: {"model": schema.Error}}) def getPet(pet_id: str = Path(..., alias="petId")) -> schema.Pets: - for k, v in ZOO.items(): - if pet_id == v.identifier: - return v + for k, pet in ZOO.items(): + if pet_id == pet.identifier: + return pet else: return JSONResponse( status_code=starlette.status.HTTP_404_NOT_FOUND, @@ -73,10 +73,10 @@ def getPet(pet_id: str = Path(..., alias="petId")) -> schema.Pets: def deletePet( response: Response, x_raise_nonexist: Annotated[Union[bool, None], Header()], - pet_id: uuid.UUID = Path(..., alias="petId"), + pet_id: str = Path(..., alias="petId"), ) -> None: - for k, v in ZOO.items(): - if pet_id == v.identifier: + for k, pet in ZOO.items(): + if pet_id == pet.identifier: del ZOO[k] response.status_code = starlette.status.HTTP_204_NO_CONTENT return response diff --git a/tests/apiv1_test.py b/tests/apiv1_test.py index 6ba187f7..047d2523 100644 --- a/tests/apiv1_test.py +++ b/tests/apiv1_test.py @@ -55,8 +55,9 @@ async def test_createPet(server, client): assert type(r).model_json_schema() == client.components.schemas["Pet"].get_type().model_json_schema() assert h["X-Limit-Remain"] == 5 - r = await asyncio.to_thread(client._.createPet, data={"pet": {"name": r.name}}) - assert type(r).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() + with pytest.raises(aiopenapi3.errors.HTTPClientError) as e: + await asyncio.to_thread(client._.createPet, data={"pet": {"name": r.name}}) + assert type(e.value.data).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() @pytest.mark.asyncio(loop_scope="session") @@ -74,15 +75,18 @@ async def test_getPet(server, client): # assert type(r).model_json_schema() == type(pet).model_json_schema() assert r.id == pet.id - r = await asyncio.to_thread(client._.getPet, parameters={"petId": -1}) - assert type(r).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() + with pytest.raises(aiopenapi3.errors.HTTPClientError) as e: + await asyncio.to_thread(client._.getPet, parameters={"petId": -1}) + + assert type(e.value.data).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() @pytest.mark.asyncio(loop_scope="session") async def test_deletePet(server, client): - r = await asyncio.to_thread(client._.deletePet, parameters={"petId": -1}) - print(r) - assert type(r).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() + with pytest.raises(aiopenapi3.errors.HTTPClientError) as e: + await asyncio.to_thread(client._.deletePet, parameters={"petId": -1}) + + assert type(e.value.data).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() await asyncio.to_thread(client._.createPet, **randomPet(uuid.uuid4())) zoo = await asyncio.to_thread(client._.listPet) diff --git a/tests/apiv2_test.py b/tests/apiv2_test.py index 58519745..40a5065c 100644 --- a/tests/apiv2_test.py +++ b/tests/apiv2_test.py @@ -180,9 +180,11 @@ async def test_createPet(server, client): r = await client._.createPet(data=data) assert isinstance(r, client.components.schemas["Cat"].get_type()) - r = await client._.createPet(data=randomPet(client, name=r.root.name)) + with pytest.raises(aiopenapi3.errors.HTTPClientError) as e: + await client._.createPet(data=randomPet(client, name=r.root.name)) + Error = client.components.schemas["Error"].get_type() - assert isinstance(r, Error) + assert isinstance(e.value.data, Error) # type(r).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() with pytest.raises(pydantic.ValidationError): @@ -196,8 +198,11 @@ async def test_listPet(server, client): l = await client._.listPet(parameters={"limit": 1}) assert len(l) > 0 - l = await client._.listPet(parameters={"limit": None}) - assert isinstance(l, client.components.schemas["HTTPValidationError"].get_type()) + with pytest.raises(aiopenapi3.errors.HTTPClientError) as e: + await client._.listPet(parameters={"limit": None}) + + Error = client.components.schemas["HTTPValidationError"].get_type() + assert isinstance(e.value.data, Error) @pytest.mark.asyncio(loop_scope="session") @@ -209,21 +214,26 @@ async def test_getPet(server, client): # https://github.com/tiangolo/fastapi/pull/10011 # assert type(r.root).model_json_schema() == type(pet.root).model_json_schema() - r = await client._.getPet(parameters={"petId": "-1"}) - assert type(r).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() + with pytest.raises(aiopenapi3.errors.HTTPClientError) as e: + await client._.getPet(parameters={"petId": "-1"}) + + assert type(e.value.data).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() @pytest.mark.asyncio(loop_scope="session") async def test_deletePet(server, client): - r = await client._.deletePet(parameters={"petId": uuid.uuid4(), "x-raise-nonexist": False}) - assert type(r).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() + + with pytest.raises(aiopenapi3.errors.HTTPClientError) as e: + await client._.deletePet(parameters={"petId": str(uuid.uuid4()), "x-raise-nonexist": True}) + + assert type(e.value.data).model_json_schema() == client.components.schemas["Error"].get_type().model_json_schema() await client._.createPet(data=randomPet(client, str(uuid.uuid4()))) zoo = await client._.listPet(parameters={"limit": 1}) for pet in zoo: while hasattr(pet, "root"): pet = pet.root - await client._.deletePet(parameters={"petId": pet.identifier, "x-raise-nonexist": None}) + await client._.deletePet(parameters={"petId": pet.identifier, "x-raise-nonexist": False}) @pytest.mark.asyncio(loop_scope="session") diff --git a/tests/path_test.py b/tests/path_test.py index 21f7b954..507f3e6a 100644 --- a/tests/path_test.py +++ b/tests/path_test.py @@ -16,8 +16,8 @@ OperationParameterValidationError, OperationIdDuplicationError, HeadersMissingError, - HttpClientError, - HttpServerError, + HTTPClientError, + HTTPServerError, ) URLBASE = "/" @@ -538,11 +538,11 @@ def test_paths_response_error(mocker, httpx_mock, with_paths_response_error_vXX) api._.test() httpx_mock.add_response(headers={"Content-Type": "application/json", "X-required": "1"}, status_code=437, json="ok") - with pytest.raises(HttpClientError): + with pytest.raises(HTTPClientError): api._.test() httpx_mock.add_response(headers={"Content-Type": "application/json", "X-required": "1"}, status_code=537, json="ok") - with pytest.raises(HttpServerError): + with pytest.raises(HTTPServerError): api._.test() httpx_mock.add_response(headers={"Content-Type": "application/json", "X-required": "1"}, status_code=437, json="ok")