From 0ee8db931fc2ab5881656287fc6f60b51d96a9de Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Wed, 10 Dec 2025 17:06:38 +0100 Subject: [PATCH] Add test for nested model with computed field in response model --- ..._schema_fals_with_nested_computed_field.py | 234 ++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 tests/test_separate_input_output_schema_fals_with_nested_computed_field.py diff --git a/tests/test_separate_input_output_schema_fals_with_nested_computed_field.py b/tests/test_separate_input_output_schema_fals_with_nested_computed_field.py new file mode 100644 index 000000000..64aaa1471 --- /dev/null +++ b/tests/test_separate_input_output_schema_fals_with_nested_computed_field.py @@ -0,0 +1,234 @@ +from typing import List + +import pytest +from fastapi import FastAPI +from fastapi.testclient import TestClient +from pydantic import BaseModel + +from .utils import needs_pydanticv2 + + +@pytest.fixture(name="client") +def get_client(): + from pydantic import computed_field + + class MyModel(BaseModel): + id: int + name: str + age: int + + @computed_field + @property + def is_adult(self) -> bool: + return self.age >= 18 + + app = FastAPI(separate_input_output_schemas=False) + + @app.get("/item") + def get_item() -> MyModel: + return MyModel(id=1, name="Alice", age=30) + + @app.get("/list") + def get_items() -> List[MyModel]: + return [MyModel(id=1, name="Alice", age=30), MyModel(id=2, name="Bob", age=17)] + + @app.post("/item") + def create_item(item: MyModel) -> MyModel: + return item + + yield TestClient(app) + + +@needs_pydanticv2 +def test_openapi(client: TestClient): + response = client.get("/openapi.json") + openapi_schema = response.json() + expected_schema = { + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "openapi": "3.1.0", + "paths": { + "/item": { + "get": { + "operationId": "get_item_item_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MyModel-Output", + }, + }, + }, + "description": "Successful Response", + }, + }, + "summary": "Get Item", + }, + "post": { + "operationId": "create_item_item_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MyModel-Input", + }, + }, + }, + "required": True, + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MyModel-Output", + }, + }, + }, + "description": "Successful Response", + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, + }, + }, + "description": "Validation Error", + }, + }, + "summary": "Create Item", + }, + }, + "/list": { + "get": { + "operationId": "get_items_list_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/MyModel-Output", + }, + "title": "Response Get Items List Get", + "type": "array", + }, + }, + }, + "description": "Successful Response", + }, + }, + "summary": "Get Items", + }, + }, + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", + }, + }, + "title": "HTTPValidationError", + "type": "object", + }, + "MyModel-Input": { + "properties": { + "age": { + "title": "Age", + "type": "integer", + }, + "id": { + "title": "Id", + "type": "integer", + }, + "name": { + "title": "Name", + "type": "string", + }, + }, + "required": [ + "id", + "name", + "age", + ], + "title": "MyModel", + "type": "object", + }, + "MyModel-Output": { + "properties": { + "age": { + "title": "Age", + "type": "integer", + }, + "id": { + "title": "Id", + "type": "integer", + }, + "is_adult": { + "readOnly": True, + "title": "Is Adult", + "type": "boolean", + }, + "name": { + "title": "Name", + "type": "string", + }, + }, + "required": [ + "id", + "name", + "age", + "is_adult", + ], + "title": "MyModel", + "type": "object", + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", + }, + }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", + }, + }, + }, + } + + assert openapi_schema == expected_schema