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

1from typing import Annotated 1abcd

2 

3import pytest 1abcd

4from fastapi import FastAPI, File, UploadFile 1abcd

5from fastapi.testclient import TestClient 1abcd

6 

7from .utils import get_body_model_name 1abcd

8 

9app = FastAPI() 1abcd

10 

11# ===================================================================================== 

12# Without aliases 

13 

14 

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

18 

19 

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

23 

24 

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

35 

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 } 

48 

49 

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 } 

71 

72 

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

85 

86 

87# ===================================================================================== 

88# Alias 

89 

90 

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

94 

95 

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

101 

102 

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

113 

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 } 

126 

127 

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 } 

149 

150 

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 } 

172 

173 

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

186 

187 

188# ===================================================================================== 

189# Validation alias 

190 

191 

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

199 

200 

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

209 

210 

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

221 

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 } 

234 

235 

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 } 

260 

261 

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)*+,-./:

273 

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 } 

284 

285 

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

298 

299 

300# ===================================================================================== 

301# Alias and validation alias 

302 

303 

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

312 

313 

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

322 

323 

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

334 

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 } 

347 

348 

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 } 

373 

374 

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

386 

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 } 

400 

401 

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

413 

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 } 

424 

425 

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