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-04-06 01:24 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +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)} 1efgh
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} 1ijkl
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() 2lbmbnbobpbqbrbsb
34 body_model_name = get_body_model_name(openapi, path) 2lbmbnbobpbqbrbsb
36 assert app.openapi()["components"]["schemas"][body_model_name] == { 2lbmbnbobpbqbrbsb
37 "properties": {
38 "p": {
39 "title": "P",
40 "type": "string",
41 "contentMediaType": "application/octet-stream",
42 },
43 },
44 "required": ["p"],
45 "title": body_model_name,
46 "type": "object",
47 }
50@pytest.mark.parametrize( 1abcd
51 "path",
52 [
53 "/required-bytes",
54 "/required-uploadfile",
55 ],
56)
57def test_required_missing(path: str): 1abcd
58 client = TestClient(app) 1KLMNOPQR
59 response = client.post(path) 1KLMNOPQR
60 assert response.status_code == 422 1KLMNOPQR
61 assert response.json() == { 1KLMNOPQR
62 "detail": [
63 {
64 "type": "missing",
65 "loc": ["body", "p"],
66 "msg": "Field required",
67 "input": None,
68 }
69 ]
70 }
73@pytest.mark.parametrize( 1abcd
74 "path",
75 [
76 "/required-bytes",
77 "/required-uploadfile",
78 ],
79)
80def test_required(path: str): 1abcd
81 client = TestClient(app) 1eifjgkhl
82 response = client.post(path, files=[("p", b"hello")]) 1eifjgkhl
83 assert response.status_code == 200 1eifjgkhl
84 assert response.json() == {"file_size": 5} 1eifjgkhl
87# =====================================================================================
88# Alias
91@app.post("/required-bytes-alias", operation_id="required_bytes_alias") 1abcd
92async def read_required_bytes_alias(p: Annotated[bytes, File(alias="p_alias")]): 1abcd
93 return {"file_size": len(p)} 1mnop
96@app.post("/required-uploadfile-alias", operation_id="required_uploadfile_alias") 1abcd
97async def read_required_uploadfile_alias( 1abcd
98 p: Annotated[UploadFile, File(alias="p_alias")],
99):
100 return {"file_size": p.size} 1qrst
103@pytest.mark.parametrize( 1abcd
104 "path",
105 [
106 "/required-bytes-alias",
107 "/required-uploadfile-alias",
108 ],
109)
110def test_required_alias_schema(path: str): 1abcd
111 openapi = app.openapi() 2tbubvbwbxbybzbAb
112 body_model_name = get_body_model_name(openapi, path) 2tbubvbwbxbybzbAb
114 assert app.openapi()["components"]["schemas"][body_model_name] == { 2tbubvbwbxbybzbAb
115 "properties": {
116 "p_alias": {
117 "title": "P Alias",
118 "type": "string",
119 "contentMediaType": "application/octet-stream",
120 },
121 },
122 "required": ["p_alias"],
123 "title": body_model_name,
124 "type": "object",
125 }
128@pytest.mark.parametrize( 1abcd
129 "path",
130 [
131 "/required-bytes-alias",
132 "/required-uploadfile-alias",
133 ],
134)
135def test_required_alias_missing(path: str): 1abcd
136 client = TestClient(app) 1STUVWXYZ
137 response = client.post(path) 1STUVWXYZ
138 assert response.status_code == 422 1STUVWXYZ
139 assert response.json() == { 1STUVWXYZ
140 "detail": [
141 {
142 "type": "missing",
143 "loc": ["body", "p_alias"],
144 "msg": "Field required",
145 "input": None,
146 }
147 ]
148 }
151@pytest.mark.parametrize( 1abcd
152 "path",
153 [
154 "/required-bytes-alias",
155 "/required-uploadfile-alias",
156 ],
157)
158def test_required_alias_by_name(path: str): 1abcd
159 client = TestClient(app) 101234567
160 response = client.post(path, files=[("p", b"hello")]) 101234567
161 assert response.status_code == 422 101234567
162 assert response.json() == { 101234567
163 "detail": [
164 {
165 "type": "missing",
166 "loc": ["body", "p_alias"],
167 "msg": "Field required",
168 "input": None,
169 }
170 ]
171 }
174@pytest.mark.parametrize( 1abcd
175 "path",
176 [
177 "/required-bytes-alias",
178 "/required-uploadfile-alias",
179 ],
180)
181def test_required_alias_by_alias(path: str): 1abcd
182 client = TestClient(app) 1mqnrospt
183 response = client.post(path, files=[("p_alias", b"hello")]) 1mqnrospt
184 assert response.status_code == 200, response.text 1mqnrospt
185 assert response.json() == {"file_size": 5} 1mqnrospt
188# =====================================================================================
189# Validation alias
192@app.post( 1abcd
193 "/required-bytes-validation-alias", operation_id="required_bytes_validation_alias"
194)
195def read_required_bytes_validation_alias( 1abcd
196 p: Annotated[bytes, File(validation_alias="p_val_alias")],
197):
198 return {"file_size": len(p)} 1uvwx
201@app.post( 1abcd
202 "/required-uploadfile-validation-alias",
203 operation_id="required_uploadfile_validation_alias",
204)
205def read_required_uploadfile_validation_alias( 1abcd
206 p: Annotated[UploadFile, File(validation_alias="p_val_alias")],
207):
208 return {"file_size": p.size} 1yzAB
211@pytest.mark.parametrize( 1abcd
212 "path",
213 [
214 "/required-bytes-validation-alias",
215 "/required-uploadfile-validation-alias",
216 ],
217)
218def test_required_validation_alias_schema(path: str): 1abcd
219 openapi = app.openapi() 2BbCbDbEbFbGbHbIb
220 body_model_name = get_body_model_name(openapi, path) 2BbCbDbEbFbGbHbIb
222 assert app.openapi()["components"]["schemas"][body_model_name] == { 2BbCbDbEbFbGbHbIb
223 "properties": {
224 "p_val_alias": {
225 "title": "P Val Alias",
226 "type": "string",
227 "contentMediaType": "application/octet-stream",
228 },
229 },
230 "required": ["p_val_alias"],
231 "title": body_model_name,
232 "type": "object",
233 }
236@pytest.mark.parametrize( 1abcd
237 "path",
238 [
239 "/required-bytes-validation-alias",
240 "/required-uploadfile-validation-alias",
241 ],
242)
243def test_required_validation_alias_missing(path: str): 1abcd
244 client = TestClient(app) 189!#$%'(
245 response = client.post(path) 189!#$%'(
246 assert response.status_code == 422 189!#$%'(
247 assert response.json() == { 189!#$%'(
248 "detail": [
249 {
250 "type": "missing",
251 "loc": [
252 "body",
253 "p_val_alias",
254 ],
255 "msg": "Field required",
256 "input": None,
257 }
258 ]
259 }
262@pytest.mark.parametrize( 1abcd
263 "path",
264 [
265 "/required-bytes-validation-alias",
266 "/required-uploadfile-validation-alias",
267 ],
268)
269def test_required_validation_alias_by_name(path: str): 1abcd
270 client = TestClient(app) 1)*+,-./:
271 response = client.post(path, files=[("p", b"hello")]) 1)*+,-./:
272 assert response.status_code == 422, response.text 1)*+,-./:
274 assert response.json() == { 1)*+,-./:
275 "detail": [
276 {
277 "type": "missing",
278 "loc": ["body", "p_val_alias"],
279 "msg": "Field required",
280 "input": None,
281 }
282 ]
283 }
286@pytest.mark.parametrize( 1abcd
287 "path",
288 [
289 "/required-bytes-validation-alias",
290 "/required-uploadfile-validation-alias",
291 ],
292)
293def test_required_validation_alias_by_validation_alias(path: str): 1abcd
294 client = TestClient(app) 1uyvzwAxB
295 response = client.post(path, files=[("p_val_alias", b"hello")]) 1uyvzwAxB
296 assert response.status_code == 200, response.text 1uyvzwAxB
297 assert response.json() == {"file_size": 5} 1uyvzwAxB
300# =====================================================================================
301# Alias and validation alias
304@app.post( 1abcd
305 "/required-bytes-alias-and-validation-alias",
306 operation_id="required_bytes_alias_and_validation_alias",
307)
308def read_required_bytes_alias_and_validation_alias( 1abcd
309 p: Annotated[bytes, File(alias="p_alias", validation_alias="p_val_alias")],
310):
311 return {"file_size": len(p)} 1CDEF
314@app.post( 1abcd
315 "/required-uploadfile-alias-and-validation-alias",
316 operation_id="required_uploadfile_alias_and_validation_alias",
317)
318def read_required_uploadfile_alias_and_validation_alias( 1abcd
319 p: Annotated[UploadFile, File(alias="p_alias", validation_alias="p_val_alias")],
320):
321 return {"file_size": p.size} 1GHIJ
324@pytest.mark.parametrize( 1abcd
325 "path",
326 [
327 "/required-bytes-alias-and-validation-alias",
328 "/required-uploadfile-alias-and-validation-alias",
329 ],
330)
331def test_required_alias_and_validation_alias_schema(path: str): 1abcd
332 openapi = app.openapi() 2JbKbLbMbNbObPbQb
333 body_model_name = get_body_model_name(openapi, path) 2JbKbLbMbNbObPbQb
335 assert app.openapi()["components"]["schemas"][body_model_name] == { 2JbKbLbMbNbObPbQb
336 "properties": {
337 "p_val_alias": {
338 "title": "P Val Alias",
339 "type": "string",
340 "contentMediaType": "application/octet-stream",
341 },
342 },
343 "required": ["p_val_alias"],
344 "title": body_model_name,
345 "type": "object",
346 }
349@pytest.mark.parametrize( 1abcd
350 "path",
351 [
352 "/required-bytes-alias-and-validation-alias",
353 "/required-uploadfile-alias-and-validation-alias",
354 ],
355)
356def test_required_alias_and_validation_alias_missing(path: str): 1abcd
357 client = TestClient(app) 1;=?@[]^_
358 response = client.post(path) 1;=?@[]^_
359 assert response.status_code == 422 1;=?@[]^_
360 assert response.json() == { 1;=?@[]^_
361 "detail": [
362 {
363 "type": "missing",
364 "loc": [
365 "body",
366 "p_val_alias",
367 ],
368 "msg": "Field required",
369 "input": None,
370 }
371 ]
372 }
375@pytest.mark.parametrize( 1abcd
376 "path",
377 [
378 "/required-bytes-alias-and-validation-alias",
379 "/required-uploadfile-alias-and-validation-alias",
380 ],
381)
382def test_required_alias_and_validation_alias_by_name(path: str): 1abcd
383 client = TestClient(app) 2` { | } ~ abbbcb
384 response = client.post(path, files={"p": "hello"}) 2` { | } ~ abbbcb
385 assert response.status_code == 422 2` { | } ~ abbbcb
387 assert response.json() == { 2` { | } ~ abbbcb
388 "detail": [
389 {
390 "type": "missing",
391 "loc": [
392 "body",
393 "p_val_alias",
394 ],
395 "msg": "Field required",
396 "input": None,
397 }
398 ]
399 }
402@pytest.mark.parametrize( 1abcd
403 "path",
404 [
405 "/required-bytes-alias-and-validation-alias",
406 "/required-uploadfile-alias-and-validation-alias",
407 ],
408)
409def test_required_alias_and_validation_alias_by_alias(path: str): 1abcd
410 client = TestClient(app) 2dbebfbgbhbibjbkb
411 response = client.post(path, files=[("p_alias", b"hello")]) 2dbebfbgbhbibjbkb
412 assert response.status_code == 422, response.text 2dbebfbgbhbibjbkb
414 assert response.json() == { 2dbebfbgbhbibjbkb
415 "detail": [
416 {
417 "type": "missing",
418 "loc": ["body", "p_val_alias"],
419 "msg": "Field required",
420 "input": None,
421 }
422 ]
423 }
426@pytest.mark.parametrize( 1abcd
427 "path",
428 [
429 "/required-bytes-alias-and-validation-alias",
430 "/required-uploadfile-alias-and-validation-alias",
431 ],
432)
433def test_required_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
434 client = TestClient(app) 1CGDHEIFJ
435 response = client.post(path, files=[("p_val_alias", b"hello")]) 1CGDHEIFJ
436 assert response.status_code == 200, response.text 1CGDHEIFJ
437 assert response.json() == {"file_size": 5} 1CGDHEIFJ