From 02a39f67b2d06a3a94b63fa1fa1268cf25eb2da7 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Sun, 17 Nov 2024 11:28:07 +0100 Subject: [PATCH] Add tests --- fastapi/dependencies/utils.py | 2 +- tests/test_multiple_params_models.py | 137 +++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 tests/test_multiple_params_models.py diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index d2cb48ad4..38bc3eb4e 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -759,7 +759,7 @@ def request_params_to_args( if model_fields: fields_to_extract = [ cached_field - for field in fields + for field in model_fields for cached_field in get_cached_model_fields(field.type_) ] diff --git a/tests/test_multiple_params_models.py b/tests/test_multiple_params_models.py new file mode 100644 index 000000000..f8d7c8b8d --- /dev/null +++ b/tests/test_multiple_params_models.py @@ -0,0 +1,137 @@ +from typing import Any, Callable + +import pytest +from fastapi import APIRouter, Cookie, FastAPI, Header, Query, status +from fastapi.testclient import TestClient +from pydantic import BaseModel +from typing_extensions import Annotated + +app = FastAPI() +client = TestClient(app) + + +class NameModel(BaseModel): + name: str + + +class AgeModel(BaseModel): + age: int + + +def add_routes( + in_: Callable[..., Any], + prefix: str, +) -> None: + router = APIRouter(prefix=prefix) + + @router.get("/models") + async def route_models( + name_model: Annotated[NameModel, in_()], + age_model: Annotated[AgeModel, in_()], + ): + return { + "name": name_model.name, + "age": age_model.age, + } + + @router.get("/mixed") + async def route_mixed( + name_model: Annotated[NameModel, in_()], + age: Annotated[int, in_()], + ): + return { + "name": name_model.name, + "age": age, + } + + app.include_router(router) + + +add_routes(Query, "/query") +add_routes(Header, "/header") +add_routes(Cookie, "/cookie") + + +@pytest.mark.parametrize( + ("in_", "prefix", "call_arg"), + [ + (Query, "/query", "params"), + (Header, "/header", "headers"), + (Cookie, "/cookie", "cookies"), + ], + ids=[ + "query", + "header", + "cookie", + ], +) +@pytest.mark.parametrize( + "type_", + [ + "models", + "mixed", + ], + ids=[ + "models", + "mixed", + ], +) +def test_multiple_params(in_, prefix, call_arg, type_): + params = {"name": "John", "age": "42"} + kwargs = {} + + if call_arg == "cookies": + client.cookies = params + else: + kwargs[call_arg] = params + + response = client.get(f"{prefix}/{type_}", **kwargs) + + assert response.status_code == status.HTTP_200_OK + assert response.json() == {"name": "John", "age": 42} + + +@pytest.mark.parametrize( + ("prefix", "in_"), + [ + ("/query", "query"), + ("/header", "header"), + ("/cookie", "cookie"), + ], + ids=[ + "query", + "header", + "cookie", + ], +) +@pytest.mark.parametrize( + "type_", + [ + "models", + "mixed", + ], + ids=[ + "models", + "mixed", + ], +) +def test_openapi_schema(prefix, in_, type_): + response = client.get("/openapi.json") + + assert response.status_code == status.HTTP_200_OK + + schema = response.json() + assert schema["paths"][f"{prefix}/{type_}"]["get"]["parameters"] == [ + { + "required": True, + "in": in_, + "name": "name", + "schema": {"title": "Name", "type": "string"}, + }, + { + "required": True, + "in": in_, + "name": "age", + "schema": {"title": "Age", "type": "integer"}, + }, + ]