如何使用APIRequestFactory测试基于令牌的身份验证?
我这个接口的查询运行得很好(只要我传入一个有效的令牌),它会返回我响应数据的json格式。
在服务的api中,有一段代码会调用我的接口,并在请求头中传递一个认证令牌:
headers = {'content-type': 'application/json',
'Authorization': 'Token {}'.format(myToken)}
url = 'http://localhost:8000/my_endpoint/'
r = session.get(url=url, params=params, headers=headers)
在views.py文件里,我有一个方法装饰器,它包裹了视图中的dispatch方法(viewsets.ReadOnlyModelViewSet):
def login_required(f):
def check_login_and_call(request, *args, **kwargs):
authentication = request.META.get('HTTP_AUTHORIZATION', b'')
if isinstance(authentication, str):
authentication = authentication.encode(HTTP_HEADER_ENCODING)
key = authentication.split()
if not key or len(key) != 2:
raise PermissionDenied('Authentication failed.')
user, token = authenticate_credentials(key[1])
return f(request, *args, **kwargs)
return check_login_and_call
我正在尝试写一个测试,用令牌来验证请求:
from rest_framework.authtoken.models import Token
from rest_framework.test import APIRequestFactory
from rest_framework.test import APITestCase
from rest_framework.test import force_authenticate
class EndpointViewTest(APITestCase):
def setUp(self):
self.factory = APIRequestFactory()
self.user = User.objects.create_user(
username='user@foo.com', email='user@foo.com', password='top_secret')
self.token = Token.objects.create(user=self.user)
self.token.save()
def test_token_auth(self):
request = self.factory.get('/my_endpoint')
force_authenticate(request, token=self.token.key)
view = views.EndpointViewSet.as_view({'get': 'list'})
response = view(request)
self.assertEqual(response.status_code, 200)
json_response = json.loads(response.render().content)['results']
但不知怎么的,我无法让这个测试中的请求正确地传递令牌。使用force_authenticate似乎并没有改变我用来验证令牌的请求头。现在的输出是“PermissionDenied: Authentication failed.”,因为请求中没有设置令牌。
有没有合适的方法可以在我的测试中设置请求头,或者重新调整我最开始使用它的方式?
4 个回答
-1
使用 APITestCase
中的内置方法来 force_authentication
的简单方法是:
class Test(APITestCase):
def setUp(self):
user1 = User.objects.create_user(username='foo')
self.client.force_authenticate(user=user1) # self.client is from APITestCase
... the rest of your tests ...
7
抱歉翻出这个老帖子,但如果有人在测试中使用 APIClient()
,你可以这样做:
from rest_framework.test import APITestCase
from rest_framework.test import APIClient
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
class VehicleCreationTests(APITestCase):
def setUp(self):
self.client = APIClient()
self.user = User.objects.create_superuser('admin', 'admin@admin.com', 'admin123')
self.token = Token.objects.create(user=self.user)
def testcase(self):
self.client.force_login(user=self.user)
response = self.client.post('/api/vehicles/', data=vehicle_data, format='json', HTTP_AUTHORIZATION=self.token)
self.assertEqual(response.status_code, 201)
我用来得出这个结论的一个非常好的资源是 django-rest-framework-jwt 测试
10
我想测试一下认证功能本身,所以不能强制进行认证。
一种正确传递令牌的方法是使用APIClient,你已经导入了这个工具。
client = APIClient()
client.credentials(HTTP_AUTHORIZATION='Token ' + self.token.key)
response = client.get('/api/vehicles/')
这样做会把你提供的令牌放入请求的头部,让后端来判断这个令牌是否有效。
34
我找到了一种方法让测试通过了,不过如果你有更好的处理办法,请分享一下。
request = self.factory.get('/my_endpoint', HTTP_AUTHORIZATION='Token {}'.format(self.token))
force_authenticate(request, user=self.user)
在修改了上面那两行测试代码后,似乎可以正确地根据令牌进行身份验证了。