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-21 17:29 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-21 17:29 +0000
1from typing import Annotated, Any 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: 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: 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(path: str, json: dict[str, Any] | None): 1abcd
225 client = TestClient(app) 1zAB
226 response = client.post(path, json=json) 1zAB
227 assert response.status_code == 422 1zAB
228 assert response.json() == { 1zAB
229 "detail": [
230 {
231 "type": "missing",
232 "loc": IsOneOf(["body", "p_val_alias"], ["body"]),
233 "msg": "Field required",
234 "input": IsOneOf(None, {}),
235 }
236 ]
237 }
240@pytest.mark.parametrize( 1abcd
241 "path",
242 [
243 "/required-validation-alias",
244 "/model-required-validation-alias",
245 ],
246)
247def test_required_validation_alias_by_name(path: str): 1abcd
248 client = TestClient(app) 1CDE
249 response = client.post(path, json={"p": "hello"}) 1CDE
250 assert response.status_code == 422, response.text 1CDE
252 assert response.json() == { 1CDE
253 "detail": [
254 {
255 "type": "missing",
256 "loc": ["body", "p_val_alias"],
257 "msg": "Field required",
258 "input": IsOneOf(None, {"p": "hello"}),
259 }
260 ]
261 }
264@pytest.mark.parametrize( 1abcd
265 "path",
266 [
267 "/required-validation-alias",
268 "/model-required-validation-alias",
269 ],
270)
271def test_required_validation_alias_by_validation_alias(path: str): 1abcd
272 client = TestClient(app) 1klm
273 response = client.post(path, json={"p_val_alias": "hello"}) 1klm
274 assert response.status_code == 200, response.text 1klm
276 assert response.json() == {"p": "hello"} 1klm
279# =====================================================================================
280# Alias and validation alias
283@app.post( 1abcd
284 "/required-alias-and-validation-alias",
285 operation_id="required_alias_and_validation_alias",
286)
287def read_required_alias_and_validation_alias( 1abcd
288 p: Annotated[
289 str, Body(embed=True, alias="p_alias", validation_alias="p_val_alias")
290 ],
291):
292 return {"p": p} 1nop
295class BodyModelRequiredAliasAndValidationAlias(BaseModel): 1abcd
296 p: str = Field(alias="p_alias", validation_alias="p_val_alias") 1abcd
299@app.post( 1abcd
300 "/model-required-alias-and-validation-alias",
301 operation_id="model_required_alias_and_validation_alias",
302)
303def read_model_required_alias_and_validation_alias( 1abcd
304 p: BodyModelRequiredAliasAndValidationAlias,
305):
306 return {"p": p.p} 1nop
309@pytest.mark.parametrize( 1abcd
310 "path",
311 [
312 "/required-alias-and-validation-alias",
313 "/model-required-alias-and-validation-alias",
314 ],
315)
316def test_required_alias_and_validation_alias_schema(path: str): 1abcd
317 openapi = app.openapi() 1XYZ
318 body_model_name = get_body_model_name(openapi, path) 1XYZ
320 assert app.openapi()["components"]["schemas"][body_model_name] == { 1XYZ
321 "properties": {
322 "p_val_alias": {"title": "P Val Alias", "type": "string"},
323 },
324 "required": ["p_val_alias"],
325 "title": body_model_name,
326 "type": "object",
327 }
330@pytest.mark.parametrize("json", [None, {}]) 1abcd
331@pytest.mark.parametrize( 1abcd
332 "path",
333 [
334 "/required-alias-and-validation-alias",
335 "/model-required-alias-and-validation-alias",
336 ],
337)
338def test_required_alias_and_validation_alias_missing( 1abcd
339 path: str, json: dict[str, Any] | None
340):
341 client = TestClient(app) 1FGH
342 response = client.post(path, json=json) 1FGH
343 assert response.status_code == 422 1FGH
344 assert response.json() == { 1FGH
345 "detail": [
346 {
347 "type": "missing",
348 "loc": IsOneOf(["body"], ["body", "p_val_alias"]),
349 "msg": "Field required",
350 "input": IsOneOf(None, {}),
351 }
352 ]
353 }
356@pytest.mark.parametrize( 1abcd
357 "path",
358 [
359 "/required-alias-and-validation-alias",
360 "/model-required-alias-and-validation-alias",
361 ],
362)
363def test_required_alias_and_validation_alias_by_name(path: str): 1abcd
364 client = TestClient(app) 1IJK
365 response = client.post(path, json={"p": "hello"}) 1IJK
366 assert response.status_code == 422 1IJK
368 assert response.json() == { 1IJK
369 "detail": [
370 {
371 "type": "missing",
372 "loc": [
373 "body",
374 "p_val_alias",
375 ],
376 "msg": "Field required",
377 "input": IsOneOf(None, {"p": "hello"}),
378 }
379 ]
380 }
383@pytest.mark.parametrize( 1abcd
384 "path",
385 [
386 "/required-alias-and-validation-alias",
387 "/model-required-alias-and-validation-alias",
388 ],
389)
390def test_required_alias_and_validation_alias_by_alias(path: str): 1abcd
391 client = TestClient(app) 1LMN
392 response = client.post(path, json={"p_alias": "hello"}) 1LMN
393 assert response.status_code == 422, response.text 1LMN
395 assert response.json() == { 1LMN
396 "detail": [
397 {
398 "type": "missing",
399 "loc": ["body", "p_val_alias"],
400 "msg": "Field required",
401 "input": IsOneOf(None, {"p_alias": "hello"}),
402 }
403 ]
404 }
407@pytest.mark.parametrize( 1abcd
408 "path",
409 [
410 "/required-alias-and-validation-alias",
411 "/model-required-alias-and-validation-alias",
412 ],
413)
414def test_required_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
415 client = TestClient(app) 1nop
416 response = client.post(path, json={"p_val_alias": "hello"}) 1nop
417 assert response.status_code == 200, response.text 1nop
419 assert response.json() == {"p": "hello"} 1nop