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

1"""Test using special types (Response, Request, BackgroundTasks) as dependency annotations. 

2 

3These tests verify that special FastAPI types can be used with Depends() annotations 

4and that the dependency injection system properly handles them. 

5""" 

6 

7from typing import Annotated 1uvwx

8 

9from fastapi import BackgroundTasks, Depends, FastAPI, Request, Response 1uvwx

10from fastapi.responses import JSONResponse 1uvwx

11from fastapi.testclient import TestClient 1uvwx

12 

13 

14def test_response_with_depends_annotated(): 1uvwx

15 """Response type hint should work with Annotated[Response, Depends(...)].""" 

16 app = FastAPI() 1mnop

17 

18 def modify_response(response: Response) -> Response: 1mnop

19 response.headers["X-Custom"] = "modified" 1mnop

20 return response 1mnop

21 

22 @app.get("/") 1mnop

23 def endpoint(response: Annotated[Response, Depends(modify_response)]): 1mnop

24 return {"status": "ok"} 1mnop

25 

26 client = TestClient(app) 1mnop

27 resp = client.get("/") 1mnop

28 

29 assert resp.status_code == 200 1mnop

30 assert resp.json() == {"status": "ok"} 1mnop

31 assert resp.headers.get("X-Custom") == "modified" 1mnop

32 

33 

34def test_response_with_depends_default(): 1uvwx

35 """Response type hint should work with Response = Depends(...).""" 

36 app = FastAPI() 1qrst

37 

38 def modify_response(response: Response) -> Response: 1qrst

39 response.headers["X-Custom"] = "modified" 1qrst

40 return response 1qrst

41 

42 @app.get("/") 1qrst

43 def endpoint(response: Response = Depends(modify_response)): 1qrst

44 return {"status": "ok"} 1qrst

45 

46 client = TestClient(app) 1qrst

47 resp = client.get("/") 1qrst

48 

49 assert resp.status_code == 200 1qrst

50 assert resp.json() == {"status": "ok"} 1qrst

51 assert resp.headers.get("X-Custom") == "modified" 1qrst

52 

53 

54def test_response_without_depends(): 1uvwx

55 """Regular Response injection should still work.""" 

56 app = FastAPI() 1yzAB

57 

58 @app.get("/") 1yzAB

59 def endpoint(response: Response): 1yzAB

60 response.headers["X-Direct"] = "set" 1yzAB

61 return {"status": "ok"} 1yzAB

62 

63 client = TestClient(app) 1yzAB

64 resp = client.get("/") 1yzAB

65 

66 assert resp.status_code == 200 1yzAB

67 assert resp.json() == {"status": "ok"} 1yzAB

68 assert resp.headers.get("X-Direct") == "set" 1yzAB

69 

70 

71def test_response_dependency_chain(): 1uvwx

72 """Response dependency should work in a chain of dependencies.""" 

73 app = FastAPI() 1efgh

74 

75 def first_modifier(response: Response) -> Response: 1efgh

76 response.headers["X-First"] = "1" 1efgh

77 return response 1efgh

78 

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

84 

85 @app.get("/") 1efgh

86 def endpoint(response: Annotated[Response, Depends(second_modifier)]): 1efgh

87 return {"status": "ok"} 1efgh

88 

89 client = TestClient(app) 1efgh

90 resp = client.get("/") 1efgh

91 

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

95 

96 

97def test_response_dependency_returns_different_response_instance(): 1uvwx

98 """Dependency that returns a different Response instance should work. 

99 

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

105 

106 def default_response() -> Response: 1ijkl

107 response = JSONResponse(content={"status": "ok"}) 1ijkl

108 response.headers["X-Custom"] = "initial" 1ijkl

109 return response 1ijkl

110 

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

115 

116 client = TestClient(app) 1ijkl

117 resp = client.get("/") 1ijkl

118 

119 assert resp.status_code == 200 1ijkl

120 assert resp.json() == {"status": "ok"} 1ijkl

121 assert resp.headers.get("X-Custom") == "modified" 1ijkl

122 

123 

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

128 

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 } 

134 

135 @app.get("/") 1CDEF

136 def endpoint( 1CDEF

137 info: Annotated[dict, Depends(extract_request_info)], 

138 ): 

139 return info 1CDEF

140 

141 client = TestClient(app) 1CDEF

142 resp = client.get("/", headers={"user-agent": "test-agent"}) 1CDEF

143 

144 assert resp.status_code == 200 1CDEF

145 assert resp.json() == {"path": "/", "user_agent": "test-agent"} 1CDEF

146 

147 

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

153 

154 def background_task(message: str): 1abcd

155 task_results.append(message) 1abcd

156 

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

160 

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

167 

168 client = TestClient(app) 1abcd

169 resp = client.get("/") 1abcd

170 

171 assert resp.status_code == 200 1abcd

172 assert "from dependency" in task_results 1abcd

173 assert "from endpoint" in task_results 1abcd