0
# Client Testing
1
2
Django test client and request factory fixtures for HTTP testing, view testing, and API testing. These fixtures provide access to Django's test client for making HTTP requests and testing views.
3
4
## Capabilities
5
6
### Django Test Client
7
8
Standard Django test client for making HTTP requests in tests.
9
10
```python { .api }
11
def client() -> django.test.Client:
12
"""
13
Django test client for HTTP requests and view testing.
14
15
Provides a test client that can make GET, POST, PUT, DELETE, and other
16
HTTP requests to your Django views. Automatically handles CSRF tokens,
17
sessions, and authentication state.
18
19
Returns:
20
django.test.Client: Configured test client instance
21
"""
22
```
23
24
Usage example:
25
```python
26
def test_view_response(client):
27
# GET request
28
response = client.get("/my-view/")
29
assert response.status_code == 200
30
assert b"Hello World" in response.content
31
32
# POST request with data
33
response = client.post("/submit/", {"name": "test", "email": "test@example.com"})
34
assert response.status_code == 302
35
36
# JSON POST request
37
import json
38
response = client.post(
39
"/api/data/",
40
json.dumps({"key": "value"}),
41
content_type="application/json"
42
)
43
assert response.status_code == 201
44
```
45
46
### Async Django Test Client
47
48
Async version of Django test client for testing async views and ASGI applications.
49
50
```python { .api }
51
def async_client() -> django.test.AsyncClient:
52
"""
53
Django async test client for async view testing.
54
55
Async version of Django's test client for testing async views,
56
ASGI applications, and async middleware. Supports all HTTP methods
57
with async/await syntax.
58
59
Returns:
60
django.test.AsyncClient: Configured async test client instance
61
"""
62
```
63
64
Usage example:
65
```python
66
import pytest
67
68
@pytest.mark.asyncio
69
async def test_async_view(async_client):
70
# Async GET request
71
response = await async_client.get("/async-view/")
72
assert response.status_code == 200
73
74
# Async POST request
75
response = await async_client.post("/async-submit/", {"data": "test"})
76
assert response.status_code == 302
77
```
78
79
### Request Factory
80
81
Django request factory for creating request objects for direct view testing.
82
83
```python { .api }
84
def rf() -> django.test.RequestFactory:
85
"""
86
Django request factory for creating request objects.
87
88
Creates request objects that can be passed directly to view functions
89
for unit testing. Unlike the test client, this doesn't run middleware
90
or URL resolution - it creates raw HttpRequest objects.
91
92
Returns:
93
django.test.RequestFactory: Request factory instance
94
"""
95
```
96
97
Usage example:
98
```python
99
def test_view_directly(rf):
100
from myapp.views import my_view
101
102
# Create GET request
103
request = rf.get("/fake-path/")
104
response = my_view(request)
105
assert response.status_code == 200
106
107
# Create POST request with data
108
request = rf.post("/fake-path/", {"name": "test"})
109
request.user = user_instance # Manually set user if needed
110
response = my_view(request)
111
assert response.status_code == 302
112
```
113
114
### Async Request Factory
115
116
Async version of Django request factory for testing async views directly.
117
118
```python { .api }
119
def async_rf() -> django.test.AsyncRequestFactory:
120
"""
121
Django async request factory for creating async request objects.
122
123
Creates async request objects for directly testing async view functions
124
without running through ASGI middleware stack. Useful for unit testing
125
async views in isolation.
126
127
Returns:
128
django.test.AsyncRequestFactory: Async request factory instance
129
"""
130
```
131
132
Usage example:
133
```python
134
import pytest
135
136
@pytest.mark.asyncio
137
async def test_async_view_directly(async_rf):
138
from myapp.views import my_async_view
139
140
# Create async GET request
141
request = async_rf.get("/fake-path/")
142
response = await my_async_view(request)
143
assert response.status_code == 200
144
145
# Create async POST request
146
request = async_rf.post("/fake-path/", {"data": "test"})
147
response = await my_async_view(request)
148
assert response.status_code == 201
149
```
150
151
## Client Types
152
153
```python { .api }
154
from django.test import Client, AsyncClient, RequestFactory, AsyncRequestFactory
155
from django.http import HttpRequest, HttpResponse
156
from typing import Dict, Any, Optional, Union
157
158
# HTTP method types
159
HttpMethodData = Dict[str, Any]
160
ContentType = str
161
StatusCode = int
162
163
# Response types from Django
164
from django.http import (
165
HttpResponse,
166
HttpResponseRedirect,
167
HttpResponsePermanentRedirect,
168
JsonResponse,
169
StreamingHttpResponse,
170
FileResponse
171
)
172
173
# Request object types
174
class HttpRequest:
175
"""Django HTTP request object."""
176
method: str
177
path: str
178
GET: Dict[str, str]
179
POST: Dict[str, str]
180
FILES: Dict[str, Any]
181
COOKIES: Dict[str, str]
182
META: Dict[str, str]
183
user: Any
184
session: Dict[str, Any]
185
186
# Test client method signatures
187
class Client:
188
def get(self, path: str, data: Optional[HttpMethodData] = None, **extra) -> HttpResponse: ...
189
def post(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpResponse: ...
190
def put(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpResponse: ...
191
def patch(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpResponse: ...
192
def delete(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpResponse: ...
193
def head(self, path: str, data: Optional[HttpMethodData] = None, **extra) -> HttpResponse: ...
194
def options(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpResponse: ...
195
def trace(self, path: str, **extra) -> HttpResponse: ...
196
def login(self, **credentials) -> bool: ...
197
def logout(self) -> None: ...
198
def force_login(self, user, backend: Optional[str] = None) -> None: ...
199
200
class AsyncClient:
201
async def get(self, path: str, data: Optional[HttpMethodData] = None, **extra) -> HttpResponse: ...
202
async def post(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpResponse: ...
203
async def put(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpResponse: ...
204
async def patch(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpResponse: ...
205
async def delete(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpResponse: ...
206
async def head(self, path: str, data: Optional[HttpMethodData] = None, **extra) -> HttpResponse: ...
207
async def options(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpResponse: ...
208
async def trace(self, path: str, **extra) -> HttpResponse: ...
209
async def login(self, **credentials) -> bool: ...
210
async def logout(self) -> None: ...
211
async def force_login(self, user, backend: Optional[str] = None) -> None: ...
212
213
class RequestFactory:
214
def get(self, path: str, data: Optional[HttpMethodData] = None, **extra) -> HttpRequest: ...
215
def post(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpRequest: ...
216
def put(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpRequest: ...
217
def patch(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpRequest: ...
218
def delete(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpRequest: ...
219
def head(self, path: str, data: Optional[HttpMethodData] = None, **extra) -> HttpRequest: ...
220
def options(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpRequest: ...
221
def trace(self, path: str, **extra) -> HttpRequest: ...
222
223
class AsyncRequestFactory:
224
def get(self, path: str, data: Optional[HttpMethodData] = None, **extra) -> HttpRequest: ...
225
def post(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpRequest: ...
226
def put(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpRequest: ...
227
def patch(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpRequest: ...
228
def delete(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpRequest: ...
229
def head(self, path: str, data: Optional[HttpMethodData] = None, **extra) -> HttpRequest: ...
230
def options(self, path: str, data: Optional[HttpMethodData] = None, content_type: Optional[ContentType] = None, **extra) -> HttpRequest: ...
231
def trace(self, path: str, **extra) -> HttpRequest: ...
232
```