Coverage for tests / test_infer_param_optionality.py: 100%

63 statements  

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

1from typing import Optional 1abcd

2 

3from fastapi import APIRouter, FastAPI 1abcd

4from fastapi.testclient import TestClient 1abcd

5from inline_snapshot import snapshot 1abcd

6 

7app = FastAPI() 1abcd

8 

9 

10user_router = APIRouter() 1abcd

11item_router = APIRouter() 1abcd

12 

13 

14@user_router.get("/") 1abcd

15def get_users(): 1abcd

16 return [{"user_id": "u1"}, {"user_id": "u2"}] 1wxy

17 

18 

19@user_router.get("/{user_id}") 1abcd

20def get_user(user_id: str): 1abcd

21 return {"user_id": user_id} 1zAB

22 

23 

24@item_router.get("/") 1abcd

25def get_items(user_id: Optional[str] = None): 1abcd

26 if user_id is None: 1efghijklm

27 return [{"item_id": "i1", "user_id": "u1"}, {"item_id": "i2", "user_id": "u2"}] 1ehk

28 else: 

29 return [{"item_id": "i2", "user_id": user_id}] 1fgijlm

30 

31 

32@item_router.get("/{item_id}") 1abcd

33def get_item(item_id: str, user_id: Optional[str] = None): 1abcd

34 if user_id is None: 1nopqrstuv

35 return {"item_id": item_id} 1nqt

36 else: 

37 return {"item_id": item_id, "user_id": user_id} 1oprsuv

38 

39 

40app.include_router(user_router, prefix="/users") 1abcd

41app.include_router(item_router, prefix="/items") 1abcd

42 

43app.include_router(item_router, prefix="/users/{user_id}/items") 1abcd

44 

45 

46client = TestClient(app) 1abcd

47 

48 

49def test_get_users(): 1abcd

50 """Check that /users returns expected data""" 

51 response = client.get("/users") 1wxy

52 assert response.status_code == 200, response.text 1wxy

53 assert response.json() == [{"user_id": "u1"}, {"user_id": "u2"}] 1wxy

54 

55 

56def test_get_user(): 1abcd

57 """Check that /users/{user_id} returns expected data""" 

58 response = client.get("/users/abc123") 1zAB

59 assert response.status_code == 200, response.text 1zAB

60 assert response.json() == {"user_id": "abc123"} 1zAB

61 

62 

63def test_get_items_1(): 1abcd

64 """Check that /items returns expected data""" 

65 response = client.get("/items") 1ehk

66 assert response.status_code == 200, response.text 1ehk

67 assert response.json() == [ 1ehk

68 {"item_id": "i1", "user_id": "u1"}, 

69 {"item_id": "i2", "user_id": "u2"}, 

70 ] 

71 

72 

73def test_get_items_2(): 1abcd

74 """Check that /items returns expected data with user_id specified""" 

75 response = client.get("/items?user_id=abc123") 1fil

76 assert response.status_code == 200, response.text 1fil

77 assert response.json() == [{"item_id": "i2", "user_id": "abc123"}] 1fil

78 

79 

80def test_get_item_1(): 1abcd

81 """Check that /items/{item_id} returns expected data""" 

82 response = client.get("/items/item01") 1nqt

83 assert response.status_code == 200, response.text 1nqt

84 assert response.json() == {"item_id": "item01"} 1nqt

85 

86 

87def test_get_item_2(): 1abcd

88 """Check that /items/{item_id} returns expected data with user_id specified""" 

89 response = client.get("/items/item01?user_id=abc123") 1oru

90 assert response.status_code == 200, response.text 1oru

91 assert response.json() == {"item_id": "item01", "user_id": "abc123"} 1oru

92 

93 

94def test_get_users_items(): 1abcd

95 """Check that /users/{user_id}/items returns expected data""" 

96 response = client.get("/users/abc123/items") 1gjm

97 assert response.status_code == 200, response.text 1gjm

98 assert response.json() == [{"item_id": "i2", "user_id": "abc123"}] 1gjm

99 

100 

101def test_get_users_item(): 1abcd

102 """Check that /users/{user_id}/items returns expected data""" 

103 response = client.get("/users/abc123/items/item01") 1psv

104 assert response.status_code == 200, response.text 1psv

105 assert response.json() == {"item_id": "item01", "user_id": "abc123"} 1psv

106 

107 

108def test_openapi_schema(): 1abcd

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

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

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

112 { 

113 "openapi": "3.1.0", 

114 "info": {"title": "FastAPI", "version": "0.1.0"}, 

115 "paths": { 

116 "/users/": { 

117 "get": { 

118 "summary": "Get Users", 

119 "operationId": "get_users_users__get", 

120 "responses": { 

121 "200": { 

122 "description": "Successful Response", 

123 "content": {"application/json": {"schema": {}}}, 

124 } 

125 }, 

126 } 

127 }, 

128 "/users/{user_id}": { 

129 "get": { 

130 "summary": "Get User", 

131 "operationId": "get_user_users__user_id__get", 

132 "parameters": [ 

133 { 

134 "required": True, 

135 "schema": {"title": "User Id", "type": "string"}, 

136 "name": "user_id", 

137 "in": "path", 

138 } 

139 ], 

140 "responses": { 

141 "200": { 

142 "description": "Successful Response", 

143 "content": {"application/json": {"schema": {}}}, 

144 }, 

145 "422": { 

146 "description": "Validation Error", 

147 "content": { 

148 "application/json": { 

149 "schema": { 

150 "$ref": "#/components/schemas/HTTPValidationError" 

151 } 

152 } 

153 }, 

154 }, 

155 }, 

156 } 

157 }, 

158 "/items/": { 

159 "get": { 

160 "summary": "Get Items", 

161 "operationId": "get_items_items__get", 

162 "parameters": [ 

163 { 

164 "required": False, 

165 "name": "user_id", 

166 "in": "query", 

167 "schema": { 

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

169 "title": "User Id", 

170 }, 

171 } 

172 ], 

173 "responses": { 

174 "200": { 

175 "description": "Successful Response", 

176 "content": {"application/json": {"schema": {}}}, 

177 }, 

178 "422": { 

179 "description": "Validation Error", 

180 "content": { 

181 "application/json": { 

182 "schema": { 

183 "$ref": "#/components/schemas/HTTPValidationError" 

184 } 

185 } 

186 }, 

187 }, 

188 }, 

189 } 

190 }, 

191 "/items/{item_id}": { 

192 "get": { 

193 "summary": "Get Item", 

194 "operationId": "get_item_items__item_id__get", 

195 "parameters": [ 

196 { 

197 "required": True, 

198 "schema": {"title": "Item Id", "type": "string"}, 

199 "name": "item_id", 

200 "in": "path", 

201 }, 

202 { 

203 "required": False, 

204 "name": "user_id", 

205 "in": "query", 

206 "schema": { 

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

208 "title": "User Id", 

209 }, 

210 }, 

211 ], 

212 "responses": { 

213 "200": { 

214 "description": "Successful Response", 

215 "content": {"application/json": {"schema": {}}}, 

216 }, 

217 "422": { 

218 "description": "Validation Error", 

219 "content": { 

220 "application/json": { 

221 "schema": { 

222 "$ref": "#/components/schemas/HTTPValidationError" 

223 } 

224 } 

225 }, 

226 }, 

227 }, 

228 } 

229 }, 

230 "/users/{user_id}/items/": { 

231 "get": { 

232 "summary": "Get Items", 

233 "operationId": "get_items_users__user_id__items__get", 

234 "parameters": [ 

235 { 

236 "required": True, 

237 "name": "user_id", 

238 "in": "path", 

239 "schema": { 

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

241 "title": "User Id", 

242 }, 

243 } 

244 ], 

245 "responses": { 

246 "200": { 

247 "description": "Successful Response", 

248 "content": {"application/json": {"schema": {}}}, 

249 }, 

250 "422": { 

251 "description": "Validation Error", 

252 "content": { 

253 "application/json": { 

254 "schema": { 

255 "$ref": "#/components/schemas/HTTPValidationError" 

256 } 

257 } 

258 }, 

259 }, 

260 }, 

261 } 

262 }, 

263 "/users/{user_id}/items/{item_id}": { 

264 "get": { 

265 "summary": "Get Item", 

266 "operationId": "get_item_users__user_id__items__item_id__get", 

267 "parameters": [ 

268 { 

269 "required": True, 

270 "schema": {"title": "Item Id", "type": "string"}, 

271 "name": "item_id", 

272 "in": "path", 

273 }, 

274 { 

275 "required": True, 

276 "name": "user_id", 

277 "in": "path", 

278 "schema": { 

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

280 "title": "User Id", 

281 }, 

282 }, 

283 ], 

284 "responses": { 

285 "200": { 

286 "description": "Successful Response", 

287 "content": {"application/json": {"schema": {}}}, 

288 }, 

289 "422": { 

290 "description": "Validation Error", 

291 "content": { 

292 "application/json": { 

293 "schema": { 

294 "$ref": "#/components/schemas/HTTPValidationError" 

295 } 

296 } 

297 }, 

298 }, 

299 }, 

300 } 

301 }, 

302 }, 

303 "components": { 

304 "schemas": { 

305 "HTTPValidationError": { 

306 "title": "HTTPValidationError", 

307 "type": "object", 

308 "properties": { 

309 "detail": { 

310 "title": "Detail", 

311 "type": "array", 

312 "items": { 

313 "$ref": "#/components/schemas/ValidationError" 

314 }, 

315 } 

316 }, 

317 }, 

318 "ValidationError": { 

319 "title": "ValidationError", 

320 "required": ["loc", "msg", "type"], 

321 "type": "object", 

322 "properties": { 

323 "loc": { 

324 "title": "Location", 

325 "type": "array", 

326 "items": { 

327 "anyOf": [{"type": "string"}, {"type": "integer"}] 

328 }, 

329 }, 

330 "msg": {"title": "Message", "type": "string"}, 

331 "type": {"title": "Error Type", "type": "string"}, 

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

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

334 }, 

335 }, 

336 } 

337 }, 

338 } 

339 )