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-04-06 01:24 +0000

1from typing import Annotated, Any 1adbc

2 

3import pytest 1adbc

4from dirty_equals import IsOneOf 1adbc

5from fastapi import Body, FastAPI 1adbc

6from fastapi.testclient import TestClient 1adbc

7from pydantic import BaseModel, Field 1adbc

8 

9from .utils import get_body_model_name 1adbc

10 

11app = FastAPI() 1adbc

12 

13# ===================================================================================== 

14# Without aliases 

15 

16 

17@app.post("/required-str", operation_id="required_str") 1adbc

18async def read_required_str(p: Annotated[str, Body(embed=True)]): 1adbc

19 return {"p": p} 1efgh

20 

21 

22class BodyModelRequiredStr(BaseModel): 1adbc

23 p: str 1abc

24 

25 

26@app.post("/model-required-str", operation_id="model_required_str") 1adbc

27async def read_model_required_str(p: BodyModelRequiredStr): 1adbc

28 return {"p": p.p} 1ijkl

29 

30 

31@pytest.mark.parametrize( 1adbc

32 "path", 

33 ["/required-str", "/model-required-str"], 

34) 

35def test_required_str_schema(path: str): 1adbc

36 openapi = app.openapi() 2JbKbLbMbNbObPbQb

37 body_model_name = get_body_model_name(openapi, path) 2JbKbLbMbNbObPbQb

38 

39 assert app.openapi()["components"]["schemas"][body_model_name] == { 2JbKbLbMbNbObPbQb

40 "properties": { 

41 "p": {"title": "P", "type": "string"}, 

42 }, 

43 "required": ["p"], 

44 "title": body_model_name, 

45 "type": "object", 

46 } 

47 

48 

49@pytest.mark.parametrize("json", [None, {}]) 1adbc

50@pytest.mark.parametrize( 1adbc

51 "path", 

52 ["/required-str", "/model-required-str"], 

53) 

54def test_required_str_missing(path: str, json: dict[str, Any] | None): 1adbc

55 client = TestClient(app) 1KLMNOPQRSTUVWX

56 response = client.post(path, json=json) 1KLMNOPQRSTUVWX

57 assert response.status_code == 422 1KLMNOPQRSTUVWX

58 assert response.json() == { 1KLMNOPQRSTUVWX

59 "detail": [ 

60 { 

61 "type": "missing", 

62 "loc": IsOneOf(["body"], ["body", "p"]), 

63 "msg": "Field required", 

64 "input": IsOneOf(None, {}), 

65 } 

66 ] 

67 } 

68 

69 

70@pytest.mark.parametrize( 1adbc

71 "path", 

72 ["/required-str", "/model-required-str"], 

73) 

74def test_required_str(path: str): 1adbc

75 client = TestClient(app) 1iejfkglh

76 response = client.post(path, json={"p": "hello"}) 1iejfkglh

77 assert response.status_code == 200 1iejfkglh

78 assert response.json() == {"p": "hello"} 1iejfkglh

79 

80 

81# ===================================================================================== 

82# Alias 

83 

84 

85@app.post("/required-alias", operation_id="required_alias") 1adbc

86async def read_required_alias( 1adbc

87 p: Annotated[str, Body(embed=True, alias="p_alias")], 

88): 

89 return {"p": p} 1mnop

90 

91 

92class BodyModelRequiredAlias(BaseModel): 1adbc

93 p: str = Field(alias="p_alias") 1adbc

94 

95 

96@app.post("/model-required-alias", operation_id="model_required_alias") 1adbc

97async def read_model_required_alias(p: BodyModelRequiredAlias): 1adbc

98 return {"p": p.p} 1qrst

99 

100 

101@pytest.mark.parametrize( 1adbc

102 "path", 

103 [ 

104 "/required-alias", 

105 "/model-required-alias", 

106 ], 

107) 

108def test_required_str_alias_schema(path: str): 1adbc

109 openapi = app.openapi() 2RbSbTbUbVbWbXbYb

110 body_model_name = get_body_model_name(openapi, path) 2RbSbTbUbVbWbXbYb

111 

112 assert app.openapi()["components"]["schemas"][body_model_name] == { 2RbSbTbUbVbWbXbYb

113 "properties": { 

114 "p_alias": {"title": "P Alias", "type": "string"}, 

115 }, 

116 "required": ["p_alias"], 

117 "title": body_model_name, 

118 "type": "object", 

119 } 

120 

121 

122@pytest.mark.parametrize("json", [None, {}]) 1adbc

123@pytest.mark.parametrize( 1adbc

124 "path", 

125 ["/required-alias", "/model-required-alias"], 

126) 

127def test_required_alias_missing(path: str, json: dict[str, Any] | None): 1adbc

128 client = TestClient(app) 1YZ0123456789!#

129 response = client.post(path, json=json) 1YZ0123456789!#

130 assert response.status_code == 422 1YZ0123456789!#

131 assert response.json() == { 1YZ0123456789!#

132 "detail": [ 

133 { 

134 "type": "missing", 

135 "loc": IsOneOf(["body", "p_alias"], ["body"]), 

136 "msg": "Field required", 

137 "input": IsOneOf(None, {}), 

138 } 

139 ] 

140 } 

141 

142 

143@pytest.mark.parametrize( 1adbc

144 "path", 

145 ["/required-alias", "/model-required-alias"], 

146) 

147def test_required_alias_by_name(path: str): 1adbc

148 client = TestClient(app) 1$%'()*+,

149 response = client.post(path, json={"p": "hello"}) 1$%'()*+,

150 assert response.status_code == 422 1$%'()*+,

151 assert response.json() == { 1$%'()*+,

152 "detail": [ 

153 { 

154 "type": "missing", 

155 "loc": ["body", "p_alias"], 

156 "msg": "Field required", 

157 "input": IsOneOf(None, {"p": "hello"}), 

158 } 

159 ] 

160 } 

161 

162 

163@pytest.mark.parametrize( 1adbc

164 "path", 

165 ["/required-alias", "/model-required-alias"], 

166) 

167def test_required_alias_by_alias(path: str): 1adbc

168 client = TestClient(app) 1qmrnsotp

169 response = client.post(path, json={"p_alias": "hello"}) 1qmrnsotp

170 assert response.status_code == 200, response.text 1qmrnsotp

171 assert response.json() == {"p": "hello"} 1qmrnsotp

172 

173 

174# ===================================================================================== 

175# Validation alias 

176 

177 

178@app.post("/required-validation-alias", operation_id="required_validation_alias") 1adbc

179def read_required_validation_alias( 1adbc

180 p: Annotated[str, Body(embed=True, validation_alias="p_val_alias")], 

181): 

182 return {"p": p} 1uvwx

183 

184 

185class BodyModelRequiredValidationAlias(BaseModel): 1adbc

186 p: str = Field(validation_alias="p_val_alias") 1adbc

187 

188 

189@app.post( 1adbc

190 "/model-required-validation-alias", operation_id="model_required_validation_alias" 

191) 

192def read_model_required_validation_alias( 1adbc

193 p: BodyModelRequiredValidationAlias, 

194): 

195 return {"p": p.p} 1yzAB

196 

197 

198@pytest.mark.parametrize( 1adbc

199 "path", 

200 ["/required-validation-alias", "/model-required-validation-alias"], 

201) 

202def test_required_validation_alias_schema(path: str): 1adbc

203 openapi = app.openapi() 2Zb0b1b2b3b4b5b6b

204 body_model_name = get_body_model_name(openapi, path) 2Zb0b1b2b3b4b5b6b

205 

206 assert app.openapi()["components"]["schemas"][body_model_name] == { 2Zb0b1b2b3b4b5b6b

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 } 

214 

215 

216@pytest.mark.parametrize("json", [None, {}]) 1adbc

217@pytest.mark.parametrize( 1adbc

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): 1adbc

225 client = TestClient(app) 1-./:;=?@[]^_`{

226 response = client.post(path, json=json) 1-./:;=?@[]^_`{

227 assert response.status_code == 422 1-./:;=?@[]^_`{

228 assert response.json() == { 1-./:;=?@[]^_`{

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 } 

238 

239 

240@pytest.mark.parametrize( 1adbc

241 "path", 

242 [ 

243 "/required-validation-alias", 

244 "/model-required-validation-alias", 

245 ], 

246) 

247def test_required_validation_alias_by_name(path: str): 1adbc

248 client = TestClient(app) 2| } ~ abbbcbdbeb

249 response = client.post(path, json={"p": "hello"}) 2| } ~ abbbcbdbeb

250 assert response.status_code == 422, response.text 2| } ~ abbbcbdbeb

251 

252 assert response.json() == { 2| } ~ abbbcbdbeb

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 } 

262 

263 

264@pytest.mark.parametrize( 1adbc

265 "path", 

266 [ 

267 "/required-validation-alias", 

268 "/model-required-validation-alias", 

269 ], 

270) 

271def test_required_validation_alias_by_validation_alias(path: str): 1adbc

272 client = TestClient(app) 1yuzvAwBx

273 response = client.post(path, json={"p_val_alias": "hello"}) 1yuzvAwBx

274 assert response.status_code == 200, response.text 1yuzvAwBx

275 

276 assert response.json() == {"p": "hello"} 1yuzvAwBx

277 

278 

279# ===================================================================================== 

280# Alias and validation alias 

281 

282 

283@app.post( 1adbc

284 "/required-alias-and-validation-alias", 

285 operation_id="required_alias_and_validation_alias", 

286) 

287def read_required_alias_and_validation_alias( 1adbc

288 p: Annotated[ 

289 str, Body(embed=True, alias="p_alias", validation_alias="p_val_alias") 

290 ], 

291): 

292 return {"p": p} 1CDEF

293 

294 

295class BodyModelRequiredAliasAndValidationAlias(BaseModel): 1adbc

296 p: str = Field(alias="p_alias", validation_alias="p_val_alias") 1adbc

297 

298 

299@app.post( 1adbc

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( 1adbc

304 p: BodyModelRequiredAliasAndValidationAlias, 

305): 

306 return {"p": p.p} 1GHIJ

307 

308 

309@pytest.mark.parametrize( 1adbc

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): 1adbc

317 openapi = app.openapi() 27b8b9b!b#b$b%b'b

318 body_model_name = get_body_model_name(openapi, path) 27b8b9b!b#b$b%b'b

319 

320 assert app.openapi()["components"]["schemas"][body_model_name] == { 27b8b9b!b#b$b%b'b

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 } 

328 

329 

330@pytest.mark.parametrize("json", [None, {}]) 1adbc

331@pytest.mark.parametrize( 1adbc

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( 1adbc

339 path: str, json: dict[str, Any] | None 

340): 

341 client = TestClient(app) 2fbgbhbibjbkblbmbnbobpbqbrbsb

342 response = client.post(path, json=json) 2fbgbhbibjbkblbmbnbobpbqbrbsb

343 assert response.status_code == 422 2fbgbhbibjbkblbmbnbobpbqbrbsb

344 assert response.json() == { 2fbgbhbibjbkblbmbnbobpbqbrbsb

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 } 

354 

355 

356@pytest.mark.parametrize( 1adbc

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): 1adbc

364 client = TestClient(app) 2tbubvbwbxbybzbAb

365 response = client.post(path, json={"p": "hello"}) 2tbubvbwbxbybzbAb

366 assert response.status_code == 422 2tbubvbwbxbybzbAb

367 

368 assert response.json() == { 2tbubvbwbxbybzbAb

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 } 

381 

382 

383@pytest.mark.parametrize( 1adbc

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): 1adbc

391 client = TestClient(app) 2BbCbDbEbFbGbHbIb

392 response = client.post(path, json={"p_alias": "hello"}) 2BbCbDbEbFbGbHbIb

393 assert response.status_code == 422, response.text 2BbCbDbEbFbGbHbIb

394 

395 assert response.json() == { 2BbCbDbEbFbGbHbIb

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 } 

405 

406 

407@pytest.mark.parametrize( 1adbc

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): 1adbc

415 client = TestClient(app) 1GCHDIEJF

416 response = client.post(path, json={"p_val_alias": "hello"}) 1GCHDIEJF

417 assert response.status_code == 200, response.text 1GCHDIEJF

418 

419 assert response.json() == {"p": "hello"} 1GCHDIEJF