Coverage for tests / test_request_params / test_body / test_required_str.py: 100%
136 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-12 18:15 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-12 18:15 +0000
1from typing import Annotated, Any, Union 1abcd
3import pytest 1abcd
4from dirty_equals import IsOneOf 1abcd
5from fastapi import Body, FastAPI 1abcd
6from fastapi.testclient import TestClient 1abcd
7from pydantic import BaseModel, Field 1abcd
9from .utils import get_body_model_name 1abcd
11app = FastAPI() 1abcd
13# =====================================================================================
14# Without aliases
17@app.post("/required-str", operation_id="required_str") 1abcd
18async def read_required_str(p: Annotated[str, Body(embed=True)]): 1abcd
19 return {"p": p} 1efg
22class BodyModelRequiredStr(BaseModel): 1abcd
23 p: str 1abcd
26@app.post("/model-required-str", operation_id="model_required_str") 1abcd
27async def read_model_required_str(p: BodyModelRequiredStr): 1abcd
28 return {"p": p.p} 1efg
31@pytest.mark.parametrize( 1abcd
32 "path",
33 ["/required-str", "/model-required-str"],
34)
35def test_required_str_schema(path: str): 1abcd
36 openapi = app.openapi() 1OPQ
37 body_model_name = get_body_model_name(openapi, path) 1OPQ
39 assert app.openapi()["components"]["schemas"][body_model_name] == { 1OPQ
40 "properties": {
41 "p": {"title": "P", "type": "string"},
42 },
43 "required": ["p"],
44 "title": body_model_name,
45 "type": "object",
46 }
49@pytest.mark.parametrize("json", [None, {}]) 1abcd
50@pytest.mark.parametrize( 1abcd
51 "path",
52 ["/required-str", "/model-required-str"],
53)
54def test_required_str_missing(path: str, json: Union[dict[str, Any], None]): 1abcd
55 client = TestClient(app) 1qrs
56 response = client.post(path, json=json) 1qrs
57 assert response.status_code == 422 1qrs
58 assert response.json() == { 1qrs
59 "detail": [
60 {
61 "type": "missing",
62 "loc": IsOneOf(["body"], ["body", "p"]),
63 "msg": "Field required",
64 "input": IsOneOf(None, {}),
65 }
66 ]
67 }
70@pytest.mark.parametrize( 1abcd
71 "path",
72 ["/required-str", "/model-required-str"],
73)
74def test_required_str(path: str): 1abcd
75 client = TestClient(app) 1efg
76 response = client.post(path, json={"p": "hello"}) 1efg
77 assert response.status_code == 200 1efg
78 assert response.json() == {"p": "hello"} 1efg
81# =====================================================================================
82# Alias
85@app.post("/required-alias", operation_id="required_alias") 1abcd
86async def read_required_alias( 1abcd
87 p: Annotated[str, Body(embed=True, alias="p_alias")],
88):
89 return {"p": p} 1hij
92class BodyModelRequiredAlias(BaseModel): 1abcd
93 p: str = Field(alias="p_alias") 1abcd
96@app.post("/model-required-alias", operation_id="model_required_alias") 1abcd
97async def read_model_required_alias(p: BodyModelRequiredAlias): 1abcd
98 return {"p": p.p} 1hij
101@pytest.mark.parametrize( 1abcd
102 "path",
103 [
104 "/required-alias",
105 "/model-required-alias",
106 ],
107)
108def test_required_str_alias_schema(path: str): 1abcd
109 openapi = app.openapi() 1RST
110 body_model_name = get_body_model_name(openapi, path) 1RST
112 assert app.openapi()["components"]["schemas"][body_model_name] == { 1RST
113 "properties": {
114 "p_alias": {"title": "P Alias", "type": "string"},
115 },
116 "required": ["p_alias"],
117 "title": body_model_name,
118 "type": "object",
119 }
122@pytest.mark.parametrize("json", [None, {}]) 1abcd
123@pytest.mark.parametrize( 1abcd
124 "path",
125 ["/required-alias", "/model-required-alias"],
126)
127def test_required_alias_missing(path: str, json: Union[dict[str, Any], None]): 1abcd
128 client = TestClient(app) 1tuv
129 response = client.post(path, json=json) 1tuv
130 assert response.status_code == 422 1tuv
131 assert response.json() == { 1tuv
132 "detail": [
133 {
134 "type": "missing",
135 "loc": IsOneOf(["body", "p_alias"], ["body"]),
136 "msg": "Field required",
137 "input": IsOneOf(None, {}),
138 }
139 ]
140 }
143@pytest.mark.parametrize( 1abcd
144 "path",
145 ["/required-alias", "/model-required-alias"],
146)
147def test_required_alias_by_name(path: str): 1abcd
148 client = TestClient(app) 1wxy
149 response = client.post(path, json={"p": "hello"}) 1wxy
150 assert response.status_code == 422 1wxy
151 assert response.json() == { 1wxy
152 "detail": [
153 {
154 "type": "missing",
155 "loc": ["body", "p_alias"],
156 "msg": "Field required",
157 "input": IsOneOf(None, {"p": "hello"}),
158 }
159 ]
160 }
163@pytest.mark.parametrize( 1abcd
164 "path",
165 ["/required-alias", "/model-required-alias"],
166)
167def test_required_alias_by_alias(path: str): 1abcd
168 client = TestClient(app) 1hij
169 response = client.post(path, json={"p_alias": "hello"}) 1hij
170 assert response.status_code == 200, response.text 1hij
171 assert response.json() == {"p": "hello"} 1hij
174# =====================================================================================
175# Validation alias
178@app.post("/required-validation-alias", operation_id="required_validation_alias") 1abcd
179def read_required_validation_alias( 1abcd
180 p: Annotated[str, Body(embed=True, validation_alias="p_val_alias")],
181):
182 return {"p": p} 1klm
185class BodyModelRequiredValidationAlias(BaseModel): 1abcd
186 p: str = Field(validation_alias="p_val_alias") 1abcd
189@app.post( 1abcd
190 "/model-required-validation-alias", operation_id="model_required_validation_alias"
191)
192def read_model_required_validation_alias( 1abcd
193 p: BodyModelRequiredValidationAlias,
194):
195 return {"p": p.p} 1klm
198@pytest.mark.parametrize( 1abcd
199 "path",
200 ["/required-validation-alias", "/model-required-validation-alias"],
201)
202def test_required_validation_alias_schema(path: str): 1abcd
203 openapi = app.openapi() 1UVW
204 body_model_name = get_body_model_name(openapi, path) 1UVW
206 assert app.openapi()["components"]["schemas"][body_model_name] == { 1UVW
207 "properties": {
208 "p_val_alias": {"title": "P Val Alias", "type": "string"},
209 },
210 "required": ["p_val_alias"],
211 "title": body_model_name,
212 "type": "object",
213 }
216@pytest.mark.parametrize("json", [None, {}]) 1abcd
217@pytest.mark.parametrize( 1abcd
218 "path",
219 [
220 "/required-validation-alias",
221 "/model-required-validation-alias",
222 ],
223)
224def test_required_validation_alias_missing( 1abcd
225 path: str, json: Union[dict[str, Any], None]
226):
227 client = TestClient(app) 1zAB
228 response = client.post(path, json=json) 1zAB
229 assert response.status_code == 422 1zAB
230 assert response.json() == { 1zAB
231 "detail": [
232 {
233 "type": "missing",
234 "loc": IsOneOf(["body", "p_val_alias"], ["body"]),
235 "msg": "Field required",
236 "input": IsOneOf(None, {}),
237 }
238 ]
239 }
242@pytest.mark.parametrize( 1abcd
243 "path",
244 [
245 "/required-validation-alias",
246 "/model-required-validation-alias",
247 ],
248)
249def test_required_validation_alias_by_name(path: str): 1abcd
250 client = TestClient(app) 1CDE
251 response = client.post(path, json={"p": "hello"}) 1CDE
252 assert response.status_code == 422, response.text 1CDE
254 assert response.json() == { 1CDE
255 "detail": [
256 {
257 "type": "missing",
258 "loc": ["body", "p_val_alias"],
259 "msg": "Field required",
260 "input": IsOneOf(None, {"p": "hello"}),
261 }
262 ]
263 }
266@pytest.mark.parametrize( 1abcd
267 "path",
268 [
269 "/required-validation-alias",
270 "/model-required-validation-alias",
271 ],
272)
273def test_required_validation_alias_by_validation_alias(path: str): 1abcd
274 client = TestClient(app) 1klm
275 response = client.post(path, json={"p_val_alias": "hello"}) 1klm
276 assert response.status_code == 200, response.text 1klm
278 assert response.json() == {"p": "hello"} 1klm
281# =====================================================================================
282# Alias and validation alias
285@app.post( 1abcd
286 "/required-alias-and-validation-alias",
287 operation_id="required_alias_and_validation_alias",
288)
289def read_required_alias_and_validation_alias( 1abcd
290 p: Annotated[
291 str, Body(embed=True, alias="p_alias", validation_alias="p_val_alias")
292 ],
293):
294 return {"p": p} 1nop
297class BodyModelRequiredAliasAndValidationAlias(BaseModel): 1abcd
298 p: str = Field(alias="p_alias", validation_alias="p_val_alias") 1abcd
301@app.post( 1abcd
302 "/model-required-alias-and-validation-alias",
303 operation_id="model_required_alias_and_validation_alias",
304)
305def read_model_required_alias_and_validation_alias( 1abcd
306 p: BodyModelRequiredAliasAndValidationAlias,
307):
308 return {"p": p.p} 1nop
311@pytest.mark.parametrize( 1abcd
312 "path",
313 [
314 "/required-alias-and-validation-alias",
315 "/model-required-alias-and-validation-alias",
316 ],
317)
318def test_required_alias_and_validation_alias_schema(path: str): 1abcd
319 openapi = app.openapi() 1XYZ
320 body_model_name = get_body_model_name(openapi, path) 1XYZ
322 assert app.openapi()["components"]["schemas"][body_model_name] == { 1XYZ
323 "properties": {
324 "p_val_alias": {"title": "P Val Alias", "type": "string"},
325 },
326 "required": ["p_val_alias"],
327 "title": body_model_name,
328 "type": "object",
329 }
332@pytest.mark.parametrize("json", [None, {}]) 1abcd
333@pytest.mark.parametrize( 1abcd
334 "path",
335 [
336 "/required-alias-and-validation-alias",
337 "/model-required-alias-and-validation-alias",
338 ],
339)
340def test_required_alias_and_validation_alias_missing( 1abcd
341 path: str, json: Union[dict[str, Any], None]
342):
343 client = TestClient(app) 1FGH
344 response = client.post(path, json=json) 1FGH
345 assert response.status_code == 422 1FGH
346 assert response.json() == { 1FGH
347 "detail": [
348 {
349 "type": "missing",
350 "loc": IsOneOf(["body"], ["body", "p_val_alias"]),
351 "msg": "Field required",
352 "input": IsOneOf(None, {}),
353 }
354 ]
355 }
358@pytest.mark.parametrize( 1abcd
359 "path",
360 [
361 "/required-alias-and-validation-alias",
362 "/model-required-alias-and-validation-alias",
363 ],
364)
365def test_required_alias_and_validation_alias_by_name(path: str): 1abcd
366 client = TestClient(app) 1IJK
367 response = client.post(path, json={"p": "hello"}) 1IJK
368 assert response.status_code == 422 1IJK
370 assert response.json() == { 1IJK
371 "detail": [
372 {
373 "type": "missing",
374 "loc": [
375 "body",
376 "p_val_alias",
377 ],
378 "msg": "Field required",
379 "input": IsOneOf(None, {"p": "hello"}),
380 }
381 ]
382 }
385@pytest.mark.parametrize( 1abcd
386 "path",
387 [
388 "/required-alias-and-validation-alias",
389 "/model-required-alias-and-validation-alias",
390 ],
391)
392def test_required_alias_and_validation_alias_by_alias(path: str): 1abcd
393 client = TestClient(app) 1LMN
394 response = client.post(path, json={"p_alias": "hello"}) 1LMN
395 assert response.status_code == 422, response.text 1LMN
397 assert response.json() == { 1LMN
398 "detail": [
399 {
400 "type": "missing",
401 "loc": ["body", "p_val_alias"],
402 "msg": "Field required",
403 "input": IsOneOf(None, {"p_alias": "hello"}),
404 }
405 ]
406 }
409@pytest.mark.parametrize( 1abcd
410 "path",
411 [
412 "/required-alias-and-validation-alias",
413 "/model-required-alias-and-validation-alias",
414 ],
415)
416def test_required_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
417 client = TestClient(app) 1nop
418 response = client.post(path, json={"p_val_alias": "hello"}) 1nop
419 assert response.status_code == 200, response.text 1nop
421 assert response.json() == {"p": "hello"} 1nop