Coverage for tests / test_response_dependency.py: 100%
100 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
1"""Test using special types (Response, Request, BackgroundTasks) as dependency annotations.
3These tests verify that special FastAPI types can be used with Depends() annotations
4and that the dependency injection system properly handles them.
5"""
7from typing import Annotated 1uvwx
9from fastapi import BackgroundTasks, Depends, FastAPI, Request, Response 1uvwx
10from fastapi.responses import JSONResponse 1uvwx
11from fastapi.testclient import TestClient 1uvwx
14def test_response_with_depends_annotated(): 1uvwx
15 """Response type hint should work with Annotated[Response, Depends(...)]."""
16 app = FastAPI() 1mnop
18 def modify_response(response: Response) -> Response: 1mnop
19 response.headers["X-Custom"] = "modified" 1mnop
20 return response 1mnop
22 @app.get("/") 1mnop
23 def endpoint(response: Annotated[Response, Depends(modify_response)]): 1mnop
24 return {"status": "ok"} 1mnop
26 client = TestClient(app) 1mnop
27 resp = client.get("/") 1mnop
29 assert resp.status_code == 200 1mnop
30 assert resp.json() == {"status": "ok"} 1mnop
31 assert resp.headers.get("X-Custom") == "modified" 1mnop
34def test_response_with_depends_default(): 1uvwx
35 """Response type hint should work with Response = Depends(...)."""
36 app = FastAPI() 1qrst
38 def modify_response(response: Response) -> Response: 1qrst
39 response.headers["X-Custom"] = "modified" 1qrst
40 return response 1qrst
42 @app.get("/") 1qrst
43 def endpoint(response: Response = Depends(modify_response)): 1qrst
44 return {"status": "ok"} 1qrst
46 client = TestClient(app) 1qrst
47 resp = client.get("/") 1qrst
49 assert resp.status_code == 200 1qrst
50 assert resp.json() == {"status": "ok"} 1qrst
51 assert resp.headers.get("X-Custom") == "modified" 1qrst
54def test_response_without_depends(): 1uvwx
55 """Regular Response injection should still work."""
56 app = FastAPI() 1yzAB
58 @app.get("/") 1yzAB
59 def endpoint(response: Response): 1yzAB
60 response.headers["X-Direct"] = "set" 1yzAB
61 return {"status": "ok"} 1yzAB
63 client = TestClient(app) 1yzAB
64 resp = client.get("/") 1yzAB
66 assert resp.status_code == 200 1yzAB
67 assert resp.json() == {"status": "ok"} 1yzAB
68 assert resp.headers.get("X-Direct") == "set" 1yzAB
71def test_response_dependency_chain(): 1uvwx
72 """Response dependency should work in a chain of dependencies."""
73 app = FastAPI() 1efgh
75 def first_modifier(response: Response) -> Response: 1efgh
76 response.headers["X-First"] = "1" 1efgh
77 return response 1efgh
79 def second_modifier( 1efgh
80 response: Annotated[Response, Depends(first_modifier)],
81 ) -> Response:
82 response.headers["X-Second"] = "2" 1efgh
83 return response 1efgh
85 @app.get("/") 1efgh
86 def endpoint(response: Annotated[Response, Depends(second_modifier)]): 1efgh
87 return {"status": "ok"} 1efgh
89 client = TestClient(app) 1efgh
90 resp = client.get("/") 1efgh
92 assert resp.status_code == 200 1efgh
93 assert resp.headers.get("X-First") == "1" 1efgh
94 assert resp.headers.get("X-Second") == "2" 1efgh
97def test_response_dependency_returns_different_response_instance(): 1uvwx
98 """Dependency that returns a different Response instance should work.
100 When a dependency returns a new Response object (e.g., JSONResponse) instead
101 of modifying the injected one, the returned response should be used and any
102 modifications to it in the endpoint should be preserved.
103 """
104 app = FastAPI() 1ijkl
106 def default_response() -> Response: 1ijkl
107 response = JSONResponse(content={"status": "ok"}) 1ijkl
108 response.headers["X-Custom"] = "initial" 1ijkl
109 return response 1ijkl
111 @app.get("/") 1ijkl
112 def endpoint(response: Annotated[Response, Depends(default_response)]): 1ijkl
113 response.headers["X-Custom"] = "modified" 1ijkl
114 return response 1ijkl
116 client = TestClient(app) 1ijkl
117 resp = client.get("/") 1ijkl
119 assert resp.status_code == 200 1ijkl
120 assert resp.json() == {"status": "ok"} 1ijkl
121 assert resp.headers.get("X-Custom") == "modified" 1ijkl
124# Tests for Request type hint with Depends
125def test_request_with_depends_annotated(): 1uvwx
126 """Request type hint should work in dependency chain."""
127 app = FastAPI() 1CDEF
129 def extract_request_info(request: Request) -> dict: 1CDEF
130 return { 1CDEF
131 "path": request.url.path,
132 "user_agent": request.headers.get("user-agent", "unknown"),
133 }
135 @app.get("/") 1CDEF
136 def endpoint( 1CDEF
137 info: Annotated[dict, Depends(extract_request_info)],
138 ):
139 return info 1CDEF
141 client = TestClient(app) 1CDEF
142 resp = client.get("/", headers={"user-agent": "test-agent"}) 1CDEF
144 assert resp.status_code == 200 1CDEF
145 assert resp.json() == {"path": "/", "user_agent": "test-agent"} 1CDEF
148# Tests for BackgroundTasks type hint with Depends
149def test_background_tasks_with_depends_annotated(): 1uvwx
150 """BackgroundTasks type hint should work with Annotated[BackgroundTasks, Depends(...)]."""
151 app = FastAPI() 1abcd
152 task_results = [] 1abcd
154 def background_task(message: str): 1abcd
155 task_results.append(message) 1abcd
157 def add_background_task(background_tasks: BackgroundTasks) -> BackgroundTasks: 1abcd
158 background_tasks.add_task(background_task, "from dependency") 1abcd
159 return background_tasks 1abcd
161 @app.get("/") 1abcd
162 def endpoint( 1abcd
163 background_tasks: Annotated[BackgroundTasks, Depends(add_background_task)],
164 ):
165 background_tasks.add_task(background_task, "from endpoint") 1abcd
166 return {"status": "ok"} 1abcd
168 client = TestClient(app) 1abcd
169 resp = client.get("/") 1abcd
171 assert resp.status_code == 200 1abcd
172 assert "from dependency" in task_results 1abcd
173 assert "from endpoint" in task_results 1abcd