Coverage for tests / test_dependency_contextmanager.py: 100%
270 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-12 18:15 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-12 18:15 +0000
1import json 1abcd
3import pytest 1abcd
4from fastapi import BackgroundTasks, Depends, FastAPI 1abcd
5from fastapi.responses import StreamingResponse 1abcd
6from fastapi.testclient import TestClient 1abcd
8app = FastAPI() 1abcd
9state = { 1abcd
10 "/async": "asyncgen not started",
11 "/sync": "generator not started",
12 "/async_raise": "asyncgen raise not started",
13 "/sync_raise": "generator raise not started",
14 "context_a": "not started a",
15 "context_b": "not started b",
16 "bg": "not set",
17 "sync_bg": "not set",
18}
20errors = [] 1abcd
23async def get_state(): 1abcd
24 return state 1UIq0ekr1Js$hltVKu23Lv%WMw4fmx5Ny'inzXOA67PB(YQC8goD9RE)jpFZSG!#TH*
27class AsyncDependencyError(Exception): 1abcd
28 pass 1abcd
31class SyncDependencyError(Exception): 1abcd
32 pass 1abcd
35class OtherDependencyError(Exception): 1abcd
36 pass 1abcd
39async def asyncgen_state(state: dict[str, str] = Depends(get_state)): 1abcd
40 state["/async"] = "asyncgen started" 10$4'8)
41 yield state["/async"] 10$4'8)
42 state["/async"] = "asyncgen completed" 10$4'8)
45def generator_state(state: dict[str, str] = Depends(get_state)): 1abcd
46 state["/sync"] = "generator started" 12%6(!*
47 yield state["/sync"] 12%6(!*
48 state["/sync"] = "generator completed" 12%6(!*
51async def asyncgen_state_try(state: dict[str, str] = Depends(get_state)): 1abcd
52 state["/async_raise"] = "asyncgen raise started" 1UIq1JsWMw5NyYQC9RE
53 try: 1UIq1JsWMw5NyYQC9RE
54 yield state["/async_raise"] 1UIq1JsWMw5NyYQC9RE
55 except AsyncDependencyError: 1UIq1JsWMw5NyYQC9RE
56 errors.append("/async_raise") 1IqJsMwNyQCRE
57 raise 1IqJsMwNyQCRE
58 finally:
59 state["/async_raise"] = "asyncgen raise finalized" 1UIq1JsWMw5NyYQC9RE
62def generator_state_try(state: dict[str, str] = Depends(get_state)): 1abcd
63 state["/sync_raise"] = "generator raise started" 1VKu3LvXOA7PBZSG#TH
64 try: 1VKu3LvXOA7PBZSG#TH
65 yield state["/sync_raise"] 1VKu3LvXOA7PBZSG#TH
66 except SyncDependencyError: 1VKu3LvXOA7PBZSG#TH
67 errors.append("/sync_raise") 1KuLvOAPBSGTH
68 raise 1KuLvOAPBSGTH
69 finally:
70 state["/sync_raise"] = "generator raise finalized" 1VKu3LvXOA7PBZSG#TH
73async def context_a(state: dict = Depends(get_state)): 1abcd
74 state["context_a"] = "started a" 1ekrhltfmxinzgoDjpF
75 try: 1ekrhltfmxinzgoDjpF
76 yield state 1ekrhltfmxinzgoDjpF
77 finally:
78 state["context_a"] = "finished a" 1ekrhltfmxinzgoDjpF
81async def context_b(state: dict = Depends(context_a)): 1abcd
82 state["context_b"] = "started b" 1ekrhltfmxinzgoDjpF
83 try: 1ekrhltfmxinzgoDjpF
84 yield state 1ekrhltfmxinzgoDjpF
85 finally:
86 state["context_b"] = f"finished b with a: {state['context_a']}" 1ekrhltfmxinzgoDjpF
89@app.get("/async") 1abcd
90async def get_async(state: str = Depends(asyncgen_state)): 1abcd
91 return state 1048
94@app.get("/sync") 1abcd
95async def get_sync(state: str = Depends(generator_state)): 1abcd
96 return state 126!
99@app.get("/async_raise") 1abcd
100async def get_async_raise(state: str = Depends(asyncgen_state_try)): 1abcd
101 assert state == "asyncgen raise started" 1IqMwQC
102 raise AsyncDependencyError() 1IqMwQC
105@app.get("/sync_raise") 1abcd
106async def get_sync_raise(state: str = Depends(generator_state_try)): 1abcd
107 assert state == "generator raise started" 1KuOASG
108 raise SyncDependencyError() 1KuOASG
111@app.get("/async_raise_other") 1abcd
112async def get_async_raise_other(state: str = Depends(asyncgen_state_try)): 1abcd
113 assert state == "asyncgen raise started" 1UWY
114 raise OtherDependencyError() 1UWY
117@app.get("/sync_raise_other") 1abcd
118async def get_sync_raise_other(state: str = Depends(generator_state_try)): 1abcd
119 assert state == "generator raise started" 1VXZ
120 raise OtherDependencyError() 1VXZ
123@app.get("/context_b") 1abcd
124async def get_context_b(state: dict = Depends(context_b)): 1abcd
125 return state 1kmo
128@app.get("/context_b_raise") 1abcd
129async def get_context_b_raise(state: dict = Depends(context_b)): 1abcd
130 assert state["context_b"] == "started b" 1rxD
131 assert state["context_a"] == "started a" 1rxD
132 raise OtherDependencyError() 1rxD
135@app.get("/context_b_bg") 1abcd
136async def get_context_b_bg(tasks: BackgroundTasks, state: dict = Depends(context_b)): 1abcd
137 async def bg(state: dict): 1efg
138 state["bg"] = f"bg set - b: {state['context_b']} - a: {state['context_a']}" 1efg
140 tasks.add_task(bg, state) 1efg
141 return state 1efg
144# Sync versions
147@app.get("/sync_async") 1abcd
148def get_sync_async(state: str = Depends(asyncgen_state)): 1abcd
149 return state 1$')
152@app.get("/sync_sync") 1abcd
153def get_sync_sync(state: str = Depends(generator_state)): 1abcd
154 return state 1%(*
157@app.get("/sync_async_raise") 1abcd
158def get_sync_async_raise(state: str = Depends(asyncgen_state_try)): 1abcd
159 assert state == "asyncgen raise started" 1JsNyRE
160 raise AsyncDependencyError() 1JsNyRE
163@app.get("/sync_sync_raise") 1abcd
164def get_sync_sync_raise(state: str = Depends(generator_state_try)): 1abcd
165 assert state == "generator raise started" 1LvPBTH
166 raise SyncDependencyError() 1LvPBTH
169@app.get("/sync_async_raise_other") 1abcd
170def get_sync_async_raise_other(state: str = Depends(asyncgen_state_try)): 1abcd
171 assert state == "asyncgen raise started" 1159
172 raise OtherDependencyError() 1159
175@app.get("/sync_sync_raise_other") 1abcd
176def get_sync_sync_raise_other(state: str = Depends(generator_state_try)): 1abcd
177 assert state == "generator raise started" 137#
178 raise OtherDependencyError() 137#
181@app.get("/sync_context_b") 1abcd
182def get_sync_context_b(state: dict = Depends(context_b)): 1abcd
183 return state 1lnp
186@app.get("/sync_context_b_raise") 1abcd
187def get_sync_context_b_raise(state: dict = Depends(context_b)): 1abcd
188 assert state["context_b"] == "started b" 1tzF
189 assert state["context_a"] == "started a" 1tzF
190 raise OtherDependencyError() 1tzF
193@app.get("/sync_context_b_bg") 1abcd
194async def get_sync_context_b_bg( 1abcd
195 tasks: BackgroundTasks, state: dict = Depends(context_b)
196):
197 async def bg(state: dict): 1hij
198 state["sync_bg"] = ( 1hij
199 f"sync_bg set - b: {state['context_b']} - a: {state['context_a']}"
200 )
202 tasks.add_task(bg, state) 1hij
203 return state 1hij
206@app.middleware("http") 1abcd
207async def middleware(request, call_next): 1abcd
208 response: StreamingResponse = await call_next(request) 1UIq0ekr1Js$hltVKu23Lv%WMw4fmx5Ny'inzXOA67PB(YQC8goD9RE)jpFZSG!#TH*
209 response.headers["x-state"] = json.dumps(state.copy()) 10ek$hl2%4fm'in6(8go)jp!*
210 return response 10ek$hl2%4fm'in6(8go)jp!*
213client = TestClient(app) 1abcd
216def test_async_state(): 1abcd
217 assert state["/async"] == "asyncgen not started" 1048
218 response = client.get("/async") 1048
219 assert response.status_code == 200, response.text 1048
220 assert response.json() == "asyncgen started" 1048
221 assert state["/async"] == "asyncgen completed" 1048
224def test_sync_state(): 1abcd
225 assert state["/sync"] == "generator not started" 126!
226 response = client.get("/sync") 126!
227 assert response.status_code == 200, response.text 126!
228 assert response.json() == "generator started" 126!
229 assert state["/sync"] == "generator completed" 126!
232def test_async_raise_other(): 1abcd
233 assert state["/async_raise"] == "asyncgen raise not started" 1UWY
234 with pytest.raises(OtherDependencyError): 1UWY
235 client.get("/async_raise_other") 1UWY
236 assert state["/async_raise"] == "asyncgen raise finalized" 1UWY
237 assert "/async_raise" not in errors 1UWY
240def test_sync_raise_other(): 1abcd
241 assert state["/sync_raise"] == "generator raise not started" 1VXZ
242 with pytest.raises(OtherDependencyError): 1VXZ
243 client.get("/sync_raise_other") 1VXZ
244 assert state["/sync_raise"] == "generator raise finalized" 1VXZ
245 assert "/sync_raise" not in errors 1VXZ
248def test_async_raise_raises(): 1abcd
249 with pytest.raises(AsyncDependencyError): 1IMQ
250 client.get("/async_raise") 1IMQ
251 assert state["/async_raise"] == "asyncgen raise finalized" 1IMQ
252 assert "/async_raise" in errors 1IMQ
253 errors.clear() 1IMQ
256def test_async_raise_server_error(): 1abcd
257 client = TestClient(app, raise_server_exceptions=False) 1qwC
258 response = client.get("/async_raise") 1qwC
259 assert response.status_code == 500, response.text 1qwC
260 assert state["/async_raise"] == "asyncgen raise finalized" 1qwC
261 assert "/async_raise" in errors 1qwC
262 errors.clear() 1qwC
265def test_context_b(): 1abcd
266 response = client.get("/context_b") 1kmo
267 data = response.json() 1kmo
268 assert data["context_b"] == "started b" 1kmo
269 assert data["context_a"] == "started a" 1kmo
270 assert state["context_b"] == "finished b with a: started a" 1kmo
271 assert state["context_a"] == "finished a" 1kmo
274def test_context_b_raise(): 1abcd
275 with pytest.raises(OtherDependencyError): 1rxD
276 client.get("/context_b_raise") 1rxD
277 assert state["context_b"] == "finished b with a: started a" 1rxD
278 assert state["context_a"] == "finished a" 1rxD
281def test_background_tasks(): 1abcd
282 response = client.get("/context_b_bg") 1efg
283 data = response.json() 1efg
284 assert data["context_b"] == "started b" 1efg
285 assert data["context_a"] == "started a" 1efg
286 assert data["bg"] == "not set" 1efg
287 middleware_state = json.loads(response.headers["x-state"]) 1efg
288 assert middleware_state["context_b"] == "started b" 1efg
289 assert middleware_state["context_a"] == "started a" 1efg
290 assert middleware_state["bg"] == "not set" 1efg
291 assert state["context_b"] == "finished b with a: started a" 1efg
292 assert state["context_a"] == "finished a" 1efg
293 assert state["bg"] == "bg set - b: started b - a: started a" 1efg
296def test_sync_raise_raises(): 1abcd
297 with pytest.raises(SyncDependencyError): 1KOS
298 client.get("/sync_raise") 1KOS
299 assert state["/sync_raise"] == "generator raise finalized" 1KOS
300 assert "/sync_raise" in errors 1KOS
301 errors.clear() 1KOS
304def test_sync_raise_server_error(): 1abcd
305 client = TestClient(app, raise_server_exceptions=False) 1uAG
306 response = client.get("/sync_raise") 1uAG
307 assert response.status_code == 500, response.text 1uAG
308 assert state["/sync_raise"] == "generator raise finalized" 1uAG
309 assert "/sync_raise" in errors 1uAG
310 errors.clear() 1uAG
313def test_sync_async_state(): 1abcd
314 response = client.get("/sync_async") 1$')
315 assert response.status_code == 200, response.text 1$')
316 assert response.json() == "asyncgen started" 1$')
317 assert state["/async"] == "asyncgen completed" 1$')
320def test_sync_sync_state(): 1abcd
321 response = client.get("/sync_sync") 1%(*
322 assert response.status_code == 200, response.text 1%(*
323 assert response.json() == "generator started" 1%(*
324 assert state["/sync"] == "generator completed" 1%(*
327def test_sync_async_raise_other(): 1abcd
328 with pytest.raises(OtherDependencyError): 1159
329 client.get("/sync_async_raise_other") 1159
330 assert state["/async_raise"] == "asyncgen raise finalized" 1159
331 assert "/async_raise" not in errors 1159
334def test_sync_sync_raise_other(): 1abcd
335 with pytest.raises(OtherDependencyError): 137#
336 client.get("/sync_sync_raise_other") 137#
337 assert state["/sync_raise"] == "generator raise finalized" 137#
338 assert "/sync_raise" not in errors 137#
341def test_sync_async_raise_raises(): 1abcd
342 with pytest.raises(AsyncDependencyError): 1JNR
343 client.get("/sync_async_raise") 1JNR
344 assert state["/async_raise"] == "asyncgen raise finalized" 1JNR
345 assert "/async_raise" in errors 1JNR
346 errors.clear() 1JNR
349def test_sync_async_raise_server_error(): 1abcd
350 client = TestClient(app, raise_server_exceptions=False) 1syE
351 response = client.get("/sync_async_raise") 1syE
352 assert response.status_code == 500, response.text 1syE
353 assert state["/async_raise"] == "asyncgen raise finalized" 1syE
354 assert "/async_raise" in errors 1syE
355 errors.clear() 1syE
358def test_sync_sync_raise_raises(): 1abcd
359 with pytest.raises(SyncDependencyError): 1LPT
360 client.get("/sync_sync_raise") 1LPT
361 assert state["/sync_raise"] == "generator raise finalized" 1LPT
362 assert "/sync_raise" in errors 1LPT
363 errors.clear() 1LPT
366def test_sync_sync_raise_server_error(): 1abcd
367 client = TestClient(app, raise_server_exceptions=False) 1vBH
368 response = client.get("/sync_sync_raise") 1vBH
369 assert response.status_code == 500, response.text 1vBH
370 assert state["/sync_raise"] == "generator raise finalized" 1vBH
371 assert "/sync_raise" in errors 1vBH
372 errors.clear() 1vBH
375def test_sync_context_b(): 1abcd
376 response = client.get("/sync_context_b") 1lnp
377 data = response.json() 1lnp
378 assert data["context_b"] == "started b" 1lnp
379 assert data["context_a"] == "started a" 1lnp
380 assert state["context_b"] == "finished b with a: started a" 1lnp
381 assert state["context_a"] == "finished a" 1lnp
384def test_sync_context_b_raise(): 1abcd
385 with pytest.raises(OtherDependencyError): 1tzF
386 client.get("/sync_context_b_raise") 1tzF
387 assert state["context_b"] == "finished b with a: started a" 1tzF
388 assert state["context_a"] == "finished a" 1tzF
391def test_sync_background_tasks(): 1abcd
392 response = client.get("/sync_context_b_bg") 1hij
393 data = response.json() 1hij
394 assert data["context_b"] == "started b" 1hij
395 assert data["context_a"] == "started a" 1hij
396 assert data["sync_bg"] == "not set" 1hij
397 assert state["context_b"] == "finished b with a: started a" 1hij
398 assert state["context_a"] == "finished a" 1hij
399 assert state["sync_bg"] == "sync_bg set - b: started b - a: started a" 1hij