Coverage for tests / test_tutorial / test_body_multiple_params / test_tutorial002.py: 100%

46 statements  

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

1import importlib 1abdc

2 

3import pytest 1abdc

4from fastapi.testclient import TestClient 1abdc

5from inline_snapshot import snapshot 1abdc

6 

7from ...utils import needs_py310 1abdc

8 

9 

10@pytest.fixture( 1abdc

11 name="client", 

12 params=[ 

13 pytest.param("tutorial002_py310", marks=needs_py310), 

14 ], 

15) 

16def get_client(request: pytest.FixtureRequest): 1abdc

17 mod = importlib.import_module(f"docs_src.body_multiple_params.{request.param}") 1abc

18 

19 client = TestClient(mod.app) 1abc

20 return client 1abc

21 

22 

23def test_post_all(client: TestClient): 1abdc

24 response = client.put( 1efg

25 "/items/5", 

26 json={ 

27 "item": { 

28 "name": "Foo", 

29 "price": 50.5, 

30 "description": "Some Foo", 

31 "tax": 0.1, 

32 }, 

33 "user": {"username": "johndoe", "full_name": "John Doe"}, 

34 }, 

35 ) 

36 assert response.status_code == 200 1efg

37 assert response.json() == { 1efg

38 "item_id": 5, 

39 "item": { 

40 "name": "Foo", 

41 "price": 50.5, 

42 "description": "Some Foo", 

43 "tax": 0.1, 

44 }, 

45 "user": {"username": "johndoe", "full_name": "John Doe"}, 

46 } 

47 

48 

49def test_post_required(client: TestClient): 1abdc

50 response = client.put( 1hij

51 "/items/5", 

52 json={ 

53 "item": {"name": "Foo", "price": 50.5}, 

54 "user": {"username": "johndoe"}, 

55 }, 

56 ) 

57 assert response.status_code == 200 1hij

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

59 "item_id": 5, 

60 "item": { 

61 "name": "Foo", 

62 "price": 50.5, 

63 "description": None, 

64 "tax": None, 

65 }, 

66 "user": {"username": "johndoe", "full_name": None}, 

67 } 

68 

69 

70def test_post_no_body(client: TestClient): 1abdc

71 response = client.put("/items/5", json=None) 1klm

72 assert response.status_code == 422 1klm

73 assert response.json() == { 1klm

74 "detail": [ 

75 { 

76 "input": None, 

77 "loc": [ 

78 "body", 

79 "item", 

80 ], 

81 "msg": "Field required", 

82 "type": "missing", 

83 }, 

84 { 

85 "input": None, 

86 "loc": [ 

87 "body", 

88 "user", 

89 ], 

90 "msg": "Field required", 

91 "type": "missing", 

92 }, 

93 ], 

94 } 

95 

96 

97def test_post_no_item(client: TestClient): 1abdc

98 response = client.put("/items/5", json={"user": {"username": "johndoe"}}) 1nop

99 assert response.status_code == 422 1nop

100 assert response.json() == { 1nop

101 "detail": [ 

102 { 

103 "input": None, 

104 "loc": [ 

105 "body", 

106 "item", 

107 ], 

108 "msg": "Field required", 

109 "type": "missing", 

110 }, 

111 ], 

112 } 

113 

114 

115def test_post_no_user(client: TestClient): 1abdc

116 response = client.put("/items/5", json={"item": {"name": "Foo", "price": 50.5}}) 1qrs

117 assert response.status_code == 422 1qrs

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

119 "detail": [ 

120 { 

121 "input": None, 

122 "loc": [ 

123 "body", 

124 "user", 

125 ], 

126 "msg": "Field required", 

127 "type": "missing", 

128 }, 

129 ], 

130 } 

131 

132 

133def test_post_missing_required_field_in_item(client: TestClient): 1abdc

134 response = client.put( 1tuv

135 "/items/5", json={"item": {"name": "Foo"}, "user": {"username": "johndoe"}} 

136 ) 

137 assert response.status_code == 422 1tuv

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

139 "detail": [ 

140 { 

141 "input": {"name": "Foo"}, 

142 "loc": [ 

143 "body", 

144 "item", 

145 "price", 

146 ], 

147 "msg": "Field required", 

148 "type": "missing", 

149 }, 

150 ], 

151 } 

152 

153 

154def test_post_missing_required_field_in_user(client: TestClient): 1abdc

155 response = client.put( 1wxy

156 "/items/5", 

157 json={"item": {"name": "Foo", "price": 50.5}, "user": {"ful_name": "John Doe"}}, 

158 ) 

159 assert response.status_code == 422 1wxy

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

161 "detail": [ 

162 { 

163 "input": {"ful_name": "John Doe"}, 

164 "loc": [ 

165 "body", 

166 "user", 

167 "username", 

168 ], 

169 "msg": "Field required", 

170 "type": "missing", 

171 }, 

172 ], 

173 } 

174 

175 

176def test_post_id_foo(client: TestClient): 1abdc

177 response = client.put( 1zAB

178 "/items/foo", 

179 json={ 

180 "item": {"name": "Foo", "price": 50.5}, 

181 "user": {"username": "johndoe"}, 

182 }, 

183 ) 

184 assert response.status_code == 422 1zAB

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

186 "detail": [ 

187 { 

188 "type": "int_parsing", 

189 "loc": ["path", "item_id"], 

190 "msg": "Input should be a valid integer, unable to parse string as an integer", 

191 "input": "foo", 

192 } 

193 ] 

194 } 

195 

196 

197def test_openapi_schema(client: TestClient): 1abdc

198 response = client.get("/openapi.json") 1CDE

199 assert response.status_code == 200, response.text 1CDE

200 assert response.json() == snapshot( 1CDE

201 { 

202 "info": { 

203 "title": "FastAPI", 

204 "version": "0.1.0", 

205 }, 

206 "openapi": "3.1.0", 

207 "paths": { 

208 "/items/{item_id}": { 

209 "put": { 

210 "operationId": "update_item_items__item_id__put", 

211 "parameters": [ 

212 { 

213 "in": "path", 

214 "name": "item_id", 

215 "required": True, 

216 "schema": { 

217 "title": "Item Id", 

218 "type": "integer", 

219 }, 

220 }, 

221 ], 

222 "requestBody": { 

223 "content": { 

224 "application/json": { 

225 "schema": { 

226 "$ref": "#/components/schemas/Body_update_item_items__item_id__put", 

227 }, 

228 }, 

229 }, 

230 "required": True, 

231 }, 

232 "responses": { 

233 "200": { 

234 "content": { 

235 "application/json": { 

236 "schema": {}, 

237 }, 

238 }, 

239 "description": "Successful Response", 

240 }, 

241 "422": { 

242 "content": { 

243 "application/json": { 

244 "schema": { 

245 "$ref": "#/components/schemas/HTTPValidationError", 

246 }, 

247 }, 

248 }, 

249 "description": "Validation Error", 

250 }, 

251 }, 

252 "summary": "Update Item", 

253 }, 

254 }, 

255 }, 

256 "components": { 

257 "schemas": { 

258 "Body_update_item_items__item_id__put": { 

259 "properties": { 

260 "item": { 

261 "$ref": "#/components/schemas/Item", 

262 }, 

263 "user": { 

264 "$ref": "#/components/schemas/User", 

265 }, 

266 }, 

267 "required": [ 

268 "item", 

269 "user", 

270 ], 

271 "title": "Body_update_item_items__item_id__put", 

272 "type": "object", 

273 }, 

274 "HTTPValidationError": { 

275 "properties": { 

276 "detail": { 

277 "items": { 

278 "$ref": "#/components/schemas/ValidationError", 

279 }, 

280 "title": "Detail", 

281 "type": "array", 

282 }, 

283 }, 

284 "title": "HTTPValidationError", 

285 "type": "object", 

286 }, 

287 "Item": { 

288 "properties": { 

289 "name": { 

290 "title": "Name", 

291 "type": "string", 

292 }, 

293 "description": { 

294 "title": "Description", 

295 "anyOf": [{"type": "string"}, {"type": "null"}], 

296 }, 

297 "price": {"title": "Price", "type": "number"}, 

298 "tax": { 

299 "title": "Tax", 

300 "anyOf": [{"type": "number"}, {"type": "null"}], 

301 }, 

302 }, 

303 "required": [ 

304 "name", 

305 "price", 

306 ], 

307 "title": "Item", 

308 "type": "object", 

309 }, 

310 "User": { 

311 "properties": { 

312 "username": { 

313 "title": "Username", 

314 "type": "string", 

315 }, 

316 "full_name": { 

317 "title": "Full Name", 

318 "anyOf": [{"type": "string"}, {"type": "null"}], 

319 }, 

320 }, 

321 "required": [ 

322 "username", 

323 ], 

324 "title": "User", 

325 "type": "object", 

326 }, 

327 "ValidationError": { 

328 "properties": { 

329 "ctx": {"title": "Context", "type": "object"}, 

330 "input": {"title": "Input"}, 

331 "loc": { 

332 "items": { 

333 "anyOf": [ 

334 { 

335 "type": "string", 

336 }, 

337 { 

338 "type": "integer", 

339 }, 

340 ], 

341 }, 

342 "title": "Location", 

343 "type": "array", 

344 }, 

345 "msg": { 

346 "title": "Message", 

347 "type": "string", 

348 }, 

349 "type": { 

350 "title": "Error Type", 

351 "type": "string", 

352 }, 

353 }, 

354 "required": [ 

355 "loc", 

356 "msg", 

357 "type", 

358 ], 

359 "title": "ValidationError", 

360 "type": "object", 

361 }, 

362 }, 

363 }, 

364 } 

365 )