Coverage for tests / test_request_params / test_query / test_required_str.py: 100%

124 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-02-12 18:15 +0000

1from typing import Annotated 1abcd

2 

3import pytest 1abcd

4from dirty_equals import IsOneOf 1abcd

5from fastapi import FastAPI, Query 1abcd

6from fastapi.testclient import TestClient 1abcd

7from inline_snapshot import snapshot 1abcd

8from pydantic import BaseModel, Field 1abcd

9 

10app = FastAPI() 1abcd

11 

12# ===================================================================================== 

13# Without aliases 

14 

15 

16@app.get("/required-str") 1abcd

17async def read_required_str(p: str): 1abcd

18 return {"p": p} 1efg

19 

20 

21class QueryModelRequiredStr(BaseModel): 1abcd

22 p: str 1abcd

23 

24 

25@app.get("/model-required-str") 1abcd

26async def read_model_required_str(p: Annotated[QueryModelRequiredStr, Query()]): 1abcd

27 return {"p": p.p} 1efg

28 

29 

30@pytest.mark.parametrize( 1abcd

31 "path", 

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

33) 

34def test_required_str_schema(path: str): 1abcd

35 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 1OPQ

36 [ 

37 { 

38 "required": True, 

39 "schema": {"title": "P", "type": "string"}, 

40 "name": "p", 

41 "in": "query", 

42 } 

43 ] 

44 ) 

45 

46 

47@pytest.mark.parametrize( 1abcd

48 "path", 

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

50) 

51def test_required_str_missing(path: str): 1abcd

52 client = TestClient(app) 1qrs

53 response = client.get(path) 1qrs

54 assert response.status_code == 422 1qrs

55 assert response.json() == { 1qrs

56 "detail": [ 

57 { 

58 "type": "missing", 

59 "loc": ["query", "p"], 

60 "msg": "Field required", 

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

62 } 

63 ] 

64 } 

65 

66 

67@pytest.mark.parametrize( 1abcd

68 "path", 

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

70) 

71def test_required_str(path: str): 1abcd

72 client = TestClient(app) 1efg

73 response = client.get(f"{path}?p=hello") 1efg

74 assert response.status_code == 200 1efg

75 assert response.json() == {"p": "hello"} 1efg

76 

77 

78# ===================================================================================== 

79# Alias 

80 

81 

82@app.get("/required-alias") 1abcd

83async def read_required_alias(p: Annotated[str, Query(alias="p_alias")]): 1abcd

84 return {"p": p} 1hij

85 

86 

87class QueryModelRequiredAlias(BaseModel): 1abcd

88 p: str = Field(alias="p_alias") 1abcd

89 

90 

91@app.get("/model-required-alias") 1abcd

92async def read_model_required_alias(p: Annotated[QueryModelRequiredAlias, Query()]): 1abcd

93 return {"p": p.p} 1hij

94 

95 

96@pytest.mark.parametrize( 1abcd

97 "path", 

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

99) 

100def test_required_str_alias_schema(path: str): 1abcd

101 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 1RST

102 [ 

103 { 

104 "required": True, 

105 "schema": {"title": "P Alias", "type": "string"}, 

106 "name": "p_alias", 

107 "in": "query", 

108 } 

109 ] 

110 ) 

111 

112 

113@pytest.mark.parametrize( 1abcd

114 "path", 

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

116) 

117def test_required_alias_missing(path: str): 1abcd

118 client = TestClient(app) 1tuv

119 response = client.get(path) 1tuv

120 assert response.status_code == 422 1tuv

121 assert response.json() == { 1tuv

122 "detail": [ 

123 { 

124 "type": "missing", 

125 "loc": ["query", "p_alias"], 

126 "msg": "Field required", 

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

128 } 

129 ] 

130 } 

131 

132 

133@pytest.mark.parametrize( 1abcd

134 "path", 

135 [ 

136 "/required-alias", 

137 "/model-required-alias", 

138 ], 

139) 

140def test_required_alias_by_name(path: str): 1abcd

141 client = TestClient(app) 1wxy

142 response = client.get(f"{path}?p=hello") 1wxy

143 assert response.status_code == 422 1wxy

144 assert response.json() == { 1wxy

145 "detail": [ 

146 { 

147 "type": "missing", 

148 "loc": ["query", "p_alias"], 

149 "msg": "Field required", 

150 "input": IsOneOf( 

151 None, 

152 {"p": "hello"}, 

153 ), 

154 } 

155 ] 

156 } 

157 

158 

159@pytest.mark.parametrize( 1abcd

160 "path", 

161 [ 

162 "/required-alias", 

163 "/model-required-alias", 

164 ], 

165) 

166def test_required_alias_by_alias(path: str): 1abcd

167 client = TestClient(app) 1hij

168 response = client.get(f"{path}?p_alias=hello") 1hij

169 assert response.status_code == 200, response.text 1hij

170 assert response.json() == {"p": "hello"} 1hij

171 

172 

173# ===================================================================================== 

174# Validation alias 

175 

176 

177@app.get("/required-validation-alias") 1abcd

178def read_required_validation_alias( 1abcd

179 p: Annotated[str, Query(validation_alias="p_val_alias")], 

180): 

181 return {"p": p} 1klm

182 

183 

184class QueryModelRequiredValidationAlias(BaseModel): 1abcd

185 p: str = Field(validation_alias="p_val_alias") 1abcd

186 

187 

188@app.get("/model-required-validation-alias") 1abcd

189def read_model_required_validation_alias( 1abcd

190 p: Annotated[QueryModelRequiredValidationAlias, Query()], 

191): 

192 return {"p": p.p} 1klm

193 

194 

195@pytest.mark.parametrize( 1abcd

196 "path", 

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

198) 

199def test_required_validation_alias_schema(path: str): 1abcd

200 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 1UVW

201 [ 

202 { 

203 "required": True, 

204 "schema": {"title": "P Val Alias", "type": "string"}, 

205 "name": "p_val_alias", 

206 "in": "query", 

207 } 

208 ] 

209 ) 

210 

211 

212@pytest.mark.parametrize( 1abcd

213 "path", 

214 [ 

215 "/required-validation-alias", 

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

217 ], 

218) 

219def test_required_validation_alias_missing(path: str): 1abcd

220 client = TestClient(app) 1zAB

221 response = client.get(path) 1zAB

222 assert response.status_code == 422 1zAB

223 assert response.json() == { 1zAB

224 "detail": [ 

225 { 

226 "type": "missing", 

227 "loc": [ 

228 "query", 

229 "p_val_alias", 

230 ], 

231 "msg": "Field required", 

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

233 } 

234 ] 

235 } 

236 

237 

238@pytest.mark.parametrize( 1abcd

239 "path", 

240 [ 

241 "/required-validation-alias", 

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

243 ], 

244) 

245def test_required_validation_alias_by_name(path: str): 1abcd

246 client = TestClient(app) 1CDE

247 response = client.get(f"{path}?p=hello") 1CDE

248 assert response.status_code == 422, response.text 1CDE

249 

250 assert response.json() == { 1CDE

251 "detail": [ 

252 { 

253 "type": "missing", 

254 "loc": ["query", "p_val_alias"], 

255 "msg": "Field required", 

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

257 } 

258 ] 

259 } 

260 

261 

262@pytest.mark.parametrize( 1abcd

263 "path", 

264 [ 

265 "/required-validation-alias", 

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

267 ], 

268) 

269def test_required_validation_alias_by_validation_alias(path: str): 1abcd

270 client = TestClient(app) 1klm

271 response = client.get(f"{path}?p_val_alias=hello") 1klm

272 assert response.status_code == 200, response.text 1klm

273 

274 assert response.json() == {"p": "hello"} 1klm

275 

276 

277# ===================================================================================== 

278# Alias and validation alias 

279 

280 

281@app.get("/required-alias-and-validation-alias") 1abcd

282def read_required_alias_and_validation_alias( 1abcd

283 p: Annotated[str, Query(alias="p_alias", validation_alias="p_val_alias")], 

284): 

285 return {"p": p} 1nop

286 

287 

288class QueryModelRequiredAliasAndValidationAlias(BaseModel): 1abcd

289 p: str = Field(alias="p_alias", validation_alias="p_val_alias") 1abcd

290 

291 

292@app.get("/model-required-alias-and-validation-alias") 1abcd

293def read_model_required_alias_and_validation_alias( 1abcd

294 p: Annotated[QueryModelRequiredAliasAndValidationAlias, Query()], 

295): 

296 return {"p": p.p} 1nop

297 

298 

299@pytest.mark.parametrize( 1abcd

300 "path", 

301 [ 

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

303 "/model-required-alias-and-validation-alias", 

304 ], 

305) 

306def test_required_alias_and_validation_alias_schema(path: str): 1abcd

307 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 1XYZ

308 [ 

309 { 

310 "required": True, 

311 "schema": {"title": "P Val Alias", "type": "string"}, 

312 "name": "p_val_alias", 

313 "in": "query", 

314 } 

315 ] 

316 ) 

317 

318 

319@pytest.mark.parametrize( 1abcd

320 "path", 

321 [ 

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

323 "/model-required-alias-and-validation-alias", 

324 ], 

325) 

326def test_required_alias_and_validation_alias_missing(path: str): 1abcd

327 client = TestClient(app) 1FGH

328 response = client.get(path) 1FGH

329 assert response.status_code == 422 1FGH

330 assert response.json() == { 1FGH

331 "detail": [ 

332 { 

333 "type": "missing", 

334 "loc": [ 

335 "query", 

336 "p_val_alias", 

337 ], 

338 "msg": "Field required", 

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

340 } 

341 ] 

342 } 

343 

344 

345@pytest.mark.parametrize( 1abcd

346 "path", 

347 [ 

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

349 "/model-required-alias-and-validation-alias", 

350 ], 

351) 

352def test_required_alias_and_validation_alias_by_name(path: str): 1abcd

353 client = TestClient(app) 1IJK

354 response = client.get(f"{path}?p=hello") 1IJK

355 assert response.status_code == 422 1IJK

356 

357 assert response.json() == { 1IJK

358 "detail": [ 

359 { 

360 "type": "missing", 

361 "loc": [ 

362 "query", 

363 "p_val_alias", 

364 ], 

365 "msg": "Field required", 

366 "input": IsOneOf( 

367 None, 

368 {"p": "hello"}, 

369 ), 

370 } 

371 ] 

372 } 

373 

374 

375@pytest.mark.parametrize( 1abcd

376 "path", 

377 [ 

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

379 "/model-required-alias-and-validation-alias", 

380 ], 

381) 

382def test_required_alias_and_validation_alias_by_alias(path: str): 1abcd

383 client = TestClient(app) 1LMN

384 response = client.get(f"{path}?p_alias=hello") 1LMN

385 assert response.status_code == 422 1LMN

386 

387 assert response.json() == { 1LMN

388 "detail": [ 

389 { 

390 "type": "missing", 

391 "loc": ["query", "p_val_alias"], 

392 "msg": "Field required", 

393 "input": IsOneOf( 

394 None, 

395 {"p_alias": "hello"}, 

396 ), 

397 } 

398 ] 

399 } 

400 

401 

402@pytest.mark.parametrize( 1abcd

403 "path", 

404 [ 

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

406 "/model-required-alias-and-validation-alias", 

407 ], 

408) 

409def test_required_alias_and_validation_alias_by_validation_alias(path: str): 1abcd

410 client = TestClient(app) 1nop

411 response = client.get(f"{path}?p_val_alias=hello") 1nop

412 assert response.status_code == 200, response.text 1nop

413 

414 assert response.json() == {"p": "hello"} 1nop