Coverage for tests / test_request_params / test_file / test_required.py: 100%
122 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 1abcd
3import pytest 1abcd
4from fastapi import FastAPI, File, UploadFile 1abcd
5from fastapi.testclient import TestClient 1abcd
7from .utils import get_body_model_name 1abcd
9app = FastAPI() 1abcd
11# =====================================================================================
12# Without aliases
15@app.post("/required-bytes", operation_id="required_bytes") 1abcd
16async def read_required_bytes(p: Annotated[bytes, File()]): 1abcd
17 return {"file_size": len(p)} 1efg
20@app.post("/required-uploadfile", operation_id="required_uploadfile") 1abcd
21async def read_required_uploadfile(p: Annotated[UploadFile, File()]): 1abcd
22 return {"file_size": p.size} 1efg
25@pytest.mark.parametrize( 1abcd
26 "path",
27 [
28 "/required-bytes",
29 "/required-uploadfile",
30 ],
31)
32def test_required_schema(path: str): 1abcd
33 openapi = app.openapi() 1OPQ
34 body_model_name = get_body_model_name(openapi, path) 1OPQ
36 assert app.openapi()["components"]["schemas"][body_model_name] == { 1OPQ
37 "properties": {
38 "p": {"title": "P", "type": "string", "format": "binary"},
39 },
40 "required": ["p"],
41 "title": body_model_name,
42 "type": "object",
43 }
46@pytest.mark.parametrize( 1abcd
47 "path",
48 [
49 "/required-bytes",
50 "/required-uploadfile",
51 ],
52)
53def test_required_missing(path: str): 1abcd
54 client = TestClient(app) 1qrs
55 response = client.post(path) 1qrs
56 assert response.status_code == 422 1qrs
57 assert response.json() == { 1qrs
58 "detail": [
59 {
60 "type": "missing",
61 "loc": ["body", "p"],
62 "msg": "Field required",
63 "input": None,
64 }
65 ]
66 }
69@pytest.mark.parametrize( 1abcd
70 "path",
71 [
72 "/required-bytes",
73 "/required-uploadfile",
74 ],
75)
76def test_required(path: str): 1abcd
77 client = TestClient(app) 1efg
78 response = client.post(path, files=[("p", b"hello")]) 1efg
79 assert response.status_code == 200 1efg
80 assert response.json() == {"file_size": 5} 1efg
83# =====================================================================================
84# Alias
87@app.post("/required-bytes-alias", operation_id="required_bytes_alias") 1abcd
88async def read_required_bytes_alias(p: Annotated[bytes, File(alias="p_alias")]): 1abcd
89 return {"file_size": len(p)} 1hij
92@app.post("/required-uploadfile-alias", operation_id="required_uploadfile_alias") 1abcd
93async def read_required_uploadfile_alias( 1abcd
94 p: Annotated[UploadFile, File(alias="p_alias")],
95):
96 return {"file_size": p.size} 1hij
99@pytest.mark.parametrize( 1abcd
100 "path",
101 [
102 "/required-bytes-alias",
103 "/required-uploadfile-alias",
104 ],
105)
106def test_required_alias_schema(path: str): 1abcd
107 openapi = app.openapi() 1RST
108 body_model_name = get_body_model_name(openapi, path) 1RST
110 assert app.openapi()["components"]["schemas"][body_model_name] == { 1RST
111 "properties": {
112 "p_alias": {"title": "P Alias", "type": "string", "format": "binary"},
113 },
114 "required": ["p_alias"],
115 "title": body_model_name,
116 "type": "object",
117 }
120@pytest.mark.parametrize( 1abcd
121 "path",
122 [
123 "/required-bytes-alias",
124 "/required-uploadfile-alias",
125 ],
126)
127def test_required_alias_missing(path: str): 1abcd
128 client = TestClient(app) 1tuv
129 response = client.post(path) 1tuv
130 assert response.status_code == 422 1tuv
131 assert response.json() == { 1tuv
132 "detail": [
133 {
134 "type": "missing",
135 "loc": ["body", "p_alias"],
136 "msg": "Field required",
137 "input": None,
138 }
139 ]
140 }
143@pytest.mark.parametrize( 1abcd
144 "path",
145 [
146 "/required-bytes-alias",
147 "/required-uploadfile-alias",
148 ],
149)
150def test_required_alias_by_name(path: str): 1abcd
151 client = TestClient(app) 1wxy
152 response = client.post(path, files=[("p", b"hello")]) 1wxy
153 assert response.status_code == 422 1wxy
154 assert response.json() == { 1wxy
155 "detail": [
156 {
157 "type": "missing",
158 "loc": ["body", "p_alias"],
159 "msg": "Field required",
160 "input": None,
161 }
162 ]
163 }
166@pytest.mark.parametrize( 1abcd
167 "path",
168 [
169 "/required-bytes-alias",
170 "/required-uploadfile-alias",
171 ],
172)
173def test_required_alias_by_alias(path: str): 1abcd
174 client = TestClient(app) 1hij
175 response = client.post(path, files=[("p_alias", b"hello")]) 1hij
176 assert response.status_code == 200, response.text 1hij
177 assert response.json() == {"file_size": 5} 1hij
180# =====================================================================================
181# Validation alias
184@app.post( 1abcd
185 "/required-bytes-validation-alias", operation_id="required_bytes_validation_alias"
186)
187def read_required_bytes_validation_alias( 1abcd
188 p: Annotated[bytes, File(validation_alias="p_val_alias")],
189):
190 return {"file_size": len(p)} 1klm
193@app.post( 1abcd
194 "/required-uploadfile-validation-alias",
195 operation_id="required_uploadfile_validation_alias",
196)
197def read_required_uploadfile_validation_alias( 1abcd
198 p: Annotated[UploadFile, File(validation_alias="p_val_alias")],
199):
200 return {"file_size": p.size} 1klm
203@pytest.mark.parametrize( 1abcd
204 "path",
205 [
206 "/required-bytes-validation-alias",
207 "/required-uploadfile-validation-alias",
208 ],
209)
210def test_required_validation_alias_schema(path: str): 1abcd
211 openapi = app.openapi() 1UVW
212 body_model_name = get_body_model_name(openapi, path) 1UVW
214 assert app.openapi()["components"]["schemas"][body_model_name] == { 1UVW
215 "properties": {
216 "p_val_alias": {
217 "title": "P Val Alias",
218 "type": "string",
219 "format": "binary",
220 },
221 },
222 "required": ["p_val_alias"],
223 "title": body_model_name,
224 "type": "object",
225 }
228@pytest.mark.parametrize( 1abcd
229 "path",
230 [
231 "/required-bytes-validation-alias",
232 "/required-uploadfile-validation-alias",
233 ],
234)
235def test_required_validation_alias_missing(path: str): 1abcd
236 client = TestClient(app) 1zAB
237 response = client.post(path) 1zAB
238 assert response.status_code == 422 1zAB
239 assert response.json() == { 1zAB
240 "detail": [
241 {
242 "type": "missing",
243 "loc": [
244 "body",
245 "p_val_alias",
246 ],
247 "msg": "Field required",
248 "input": None,
249 }
250 ]
251 }
254@pytest.mark.parametrize( 1abcd
255 "path",
256 [
257 "/required-bytes-validation-alias",
258 "/required-uploadfile-validation-alias",
259 ],
260)
261def test_required_validation_alias_by_name(path: str): 1abcd
262 client = TestClient(app) 1CDE
263 response = client.post(path, files=[("p", b"hello")]) 1CDE
264 assert response.status_code == 422, response.text 1CDE
266 assert response.json() == { 1CDE
267 "detail": [
268 {
269 "type": "missing",
270 "loc": ["body", "p_val_alias"],
271 "msg": "Field required",
272 "input": None,
273 }
274 ]
275 }
278@pytest.mark.parametrize( 1abcd
279 "path",
280 [
281 "/required-bytes-validation-alias",
282 "/required-uploadfile-validation-alias",
283 ],
284)
285def test_required_validation_alias_by_validation_alias(path: str): 1abcd
286 client = TestClient(app) 1klm
287 response = client.post(path, files=[("p_val_alias", b"hello")]) 1klm
288 assert response.status_code == 200, response.text 1klm
289 assert response.json() == {"file_size": 5} 1klm
292# =====================================================================================
293# Alias and validation alias
296@app.post( 1abcd
297 "/required-bytes-alias-and-validation-alias",
298 operation_id="required_bytes_alias_and_validation_alias",
299)
300def read_required_bytes_alias_and_validation_alias( 1abcd
301 p: Annotated[bytes, File(alias="p_alias", validation_alias="p_val_alias")],
302):
303 return {"file_size": len(p)} 1nop
306@app.post( 1abcd
307 "/required-uploadfile-alias-and-validation-alias",
308 operation_id="required_uploadfile_alias_and_validation_alias",
309)
310def read_required_uploadfile_alias_and_validation_alias( 1abcd
311 p: Annotated[UploadFile, File(alias="p_alias", validation_alias="p_val_alias")],
312):
313 return {"file_size": p.size} 1nop
316@pytest.mark.parametrize( 1abcd
317 "path",
318 [
319 "/required-bytes-alias-and-validation-alias",
320 "/required-uploadfile-alias-and-validation-alias",
321 ],
322)
323def test_required_alias_and_validation_alias_schema(path: str): 1abcd
324 openapi = app.openapi() 1XYZ
325 body_model_name = get_body_model_name(openapi, path) 1XYZ
327 assert app.openapi()["components"]["schemas"][body_model_name] == { 1XYZ
328 "properties": {
329 "p_val_alias": {
330 "title": "P Val Alias",
331 "type": "string",
332 "format": "binary",
333 },
334 },
335 "required": ["p_val_alias"],
336 "title": body_model_name,
337 "type": "object",
338 }
341@pytest.mark.parametrize( 1abcd
342 "path",
343 [
344 "/required-bytes-alias-and-validation-alias",
345 "/required-uploadfile-alias-and-validation-alias",
346 ],
347)
348def test_required_alias_and_validation_alias_missing(path: str): 1abcd
349 client = TestClient(app) 1FGH
350 response = client.post(path) 1FGH
351 assert response.status_code == 422 1FGH
352 assert response.json() == { 1FGH
353 "detail": [
354 {
355 "type": "missing",
356 "loc": [
357 "body",
358 "p_val_alias",
359 ],
360 "msg": "Field required",
361 "input": None,
362 }
363 ]
364 }
367@pytest.mark.parametrize( 1abcd
368 "path",
369 [
370 "/required-bytes-alias-and-validation-alias",
371 "/required-uploadfile-alias-and-validation-alias",
372 ],
373)
374def test_required_alias_and_validation_alias_by_name(path: str): 1abcd
375 client = TestClient(app) 1IJK
376 response = client.post(path, files={"p": "hello"}) 1IJK
377 assert response.status_code == 422 1IJK
379 assert response.json() == { 1IJK
380 "detail": [
381 {
382 "type": "missing",
383 "loc": [
384 "body",
385 "p_val_alias",
386 ],
387 "msg": "Field required",
388 "input": None,
389 }
390 ]
391 }
394@pytest.mark.parametrize( 1abcd
395 "path",
396 [
397 "/required-bytes-alias-and-validation-alias",
398 "/required-uploadfile-alias-and-validation-alias",
399 ],
400)
401def test_required_alias_and_validation_alias_by_alias(path: str): 1abcd
402 client = TestClient(app) 1LMN
403 response = client.post(path, files=[("p_alias", b"hello")]) 1LMN
404 assert response.status_code == 422, response.text 1LMN
406 assert response.json() == { 1LMN
407 "detail": [
408 {
409 "type": "missing",
410 "loc": ["body", "p_val_alias"],
411 "msg": "Field required",
412 "input": None,
413 }
414 ]
415 }
418@pytest.mark.parametrize( 1abcd
419 "path",
420 [
421 "/required-bytes-alias-and-validation-alias",
422 "/required-uploadfile-alias-and-validation-alias",
423 ],
424)
425def test_required_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
426 client = TestClient(app) 1nop
427 response = client.post(path, files=[("p_val_alias", b"hello")]) 1nop
428 assert response.status_code == 200, response.text 1nop
429 assert response.json() == {"file_size": 5} 1nop