Coverage for tests / test_response_dependency.py: 100%
100 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
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 1pqrs
9from fastapi import BackgroundTasks, Depends, FastAPI, Request, Response 1pqrs
10from fastapi.responses import JSONResponse 1pqrs
11from fastapi.testclient import TestClient 1pqrs
14def test_response_with_depends_annotated(): 1pqrs
15 """Response type hint should work with Annotated[Response, Depends(...)]."""
16 app = FastAPI() 1jkl
18 def modify_response(response: Response) -> Response: 1jkl
19 response.headers["X-Custom"] = "modified" 1jkl
20 return response 1jkl
22 @app.get("/") 1jkl
23 def endpoint(response: Annotated[Response, Depends(modify_response)]): 1jkl
24 return {"status": "ok"} 1jkl
26 client = TestClient(app) 1jkl
27 resp = client.get("/") 1jkl
29 assert resp.status_code == 200 1jkl
30 assert resp.json() == {"status": "ok"} 1jkl
31 assert resp.headers.get("X-Custom") == "modified" 1jkl
34def test_response_with_depends_default(): 1pqrs
35 """Response type hint should work with Response = Depends(...)."""
36 app = FastAPI() 1mno
38 def modify_response(response: Response) -> Response: 1mno
39 response.headers["X-Custom"] = "modified" 1mno
40 return response 1mno
42 @app.get("/") 1mno
43 def endpoint(response: Response = Depends(modify_response)): 1mno
44 return {"status": "ok"} 1mno
46 client = TestClient(app) 1mno
47 resp = client.get("/") 1mno
49 assert resp.status_code == 200 1mno
50 assert resp.json() == {"status": "ok"} 1mno
51 assert resp.headers.get("X-Custom") == "modified" 1mno
54def test_response_without_depends(): 1pqrs
55 """Regular Response injection should still work."""
56 app = FastAPI() 1tuv
58 @app.get("/") 1tuv
59 def endpoint(response: Response): 1tuv
60 response.headers["X-Direct"] = "set" 1tuv
61 return {"status": "ok"} 1tuv
63 client = TestClient(app) 1tuv
64 resp = client.get("/") 1tuv
66 assert resp.status_code == 200 1tuv
67 assert resp.json() == {"status": "ok"} 1tuv
68 assert resp.headers.get("X-Direct") == "set" 1tuv
71def test_response_dependency_chain(): 1pqrs
72 """Response dependency should work in a chain of dependencies."""
73 app = FastAPI() 1def
75 def first_modifier(response: Response) -> Response: 1def
76 response.headers["X-First"] = "1" 1def
77 return response 1def
79 def second_modifier( 1def
80 response: Annotated[Response, Depends(first_modifier)],
81 ) -> Response:
82 response.headers["X-Second"] = "2" 1def
83 return response 1def
85 @app.get("/") 1def
86 def endpoint(response: Annotated[Response, Depends(second_modifier)]): 1def
87 return {"status": "ok"} 1def
89 client = TestClient(app) 1def
90 resp = client.get("/") 1def
92 assert resp.status_code == 200 1def
93 assert resp.headers.get("X-First") == "1" 1def
94 assert resp.headers.get("X-Second") == "2" 1def
97def test_response_dependency_returns_different_response_instance(): 1pqrs
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() 1ghi
106 def default_response() -> Response: 1ghi
107 response = JSONResponse(content={"status": "ok"}) 1ghi
108 response.headers["X-Custom"] = "initial" 1ghi
109 return response 1ghi
111 @app.get("/") 1ghi
112 def endpoint(response: Annotated[Response, Depends(default_response)]): 1ghi
113 response.headers["X-Custom"] = "modified" 1ghi
114 return response 1ghi
116 client = TestClient(app) 1ghi
117 resp = client.get("/") 1ghi
119 assert resp.status_code == 200 1ghi
120 assert resp.json() == {"status": "ok"} 1ghi
121 assert resp.headers.get("X-Custom") == "modified" 1ghi
124# Tests for Request type hint with Depends
125def test_request_with_depends_annotated(): 1pqrs
126 """Request type hint should work in dependency chain."""
127 app = FastAPI() 1wxy
129 def extract_request_info(request: Request) -> dict: 1wxy
130 return { 1wxy
131 "path": request.url.path,
132 "user_agent": request.headers.get("user-agent", "unknown"),
133 }
135 @app.get("/") 1wxy
136 def endpoint( 1wxy
137 info: Annotated[dict, Depends(extract_request_info)],
138 ):
139 return info 1wxy
141 client = TestClient(app) 1wxy
142 resp = client.get("/", headers={"user-agent": "test-agent"}) 1wxy
144 assert resp.status_code == 200 1wxy
145 assert resp.json() == {"path": "/", "user_agent": "test-agent"} 1wxy
148# Tests for BackgroundTasks type hint with Depends
149def test_background_tasks_with_depends_annotated(): 1pqrs
150 """BackgroundTasks type hint should work with Annotated[BackgroundTasks, Depends(...)]."""
151 app = FastAPI() 1abc
152 task_results = [] 1abc
154 def background_task(message: str): 1abc
155 task_results.append(message) 1abc
157 def add_background_task(background_tasks: BackgroundTasks) -> BackgroundTasks: 1abc
158 background_tasks.add_task(background_task, "from dependency") 1abc
159 return background_tasks 1abc
161 @app.get("/") 1abc
162 def endpoint( 1abc
163 background_tasks: Annotated[BackgroundTasks, Depends(add_background_task)],
164 ):
165 background_tasks.add_task(background_task, "from endpoint") 1abc
166 return {"status": "ok"} 1abc
168 client = TestClient(app) 1abc
169 resp = client.get("/") 1abc
171 assert resp.status_code == 200 1abc
172 assert "from dependency" in task_results 1abc
173 assert "from endpoint" in task_results 1abc