認証にJWTパッケージでDRFを使用しています。ここで、JWTトークンを使用して自身を認証する単体テストを記述しようとしています。どのように試しても、テストAPIクライアントがJWTを介して自身を認証することはできません。 APIクライアント(私の場合はPostman)でも同じことをすると、すべてが機能します。
これはテストケースです:
_from Django.urls import reverse
from rest_framework.test import APITestCase
from rest_framework_jwt.settings import api_settings
from backend.factories import member_factory
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
class MemberTests(APITestCase):
def test_get_member(self):
member = member_factory()
payload = jwt_payload_handler(member.user)
token = jwt_encode_handler(payload)
self.client.credentials(Authorization='JWT {0}'.format(token))
response = self.client.get(reverse('member-detail', kwargs={'pk': member.pk}))
assert response.status_code == 200
_
しかし、常に_401 Authentication credentials were not provided
_を取得します。
_response.request
_にはトークンが表示されていますが、適用されていないようです。
_rest_framework.test.RequestsClient
_を使用するようにテストを書き直し、実際にそれを live_server URLに送信すると、動作します。
これについて何か助けはありますか?
追伸force_authenticate()
と login は知っていますが、本番環境のAPIクライアントと同じように、単体テストでAPIにアクセスしたいと思います。
このテスト用に新しいAPIClientをセットアップしてみてください。これは私自身のテストがどのように見えるかです
def test_api_jwt(self):
url = reverse('api-jwt-auth')
u = user_model.objects.create_user(username='user', email='[email protected]', password='pass')
u.is_active = False
u.save()
resp = self.client.post(url, {'email':'[email protected]', 'password':'pass'}, format='json')
self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
u.is_active = True
u.save()
resp = self.client.post(url, {'username':'[email protected]', 'password':'pass'}, format='json')
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertTrue('token' in resp.data)
token = resp.data['token']
#print(token)
verification_url = reverse('api-jwt-verify')
resp = self.client.post(verification_url, {'token': token}, format='json')
self.assertEqual(resp.status_code, status.HTTP_200_OK)
resp = self.client.post(verification_url, {'token': 'abc'}, format='json')
self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
client = APIClient()
client.credentials(HTTP_AUTHORIZATION='JWT ' + 'abc')
resp = client.get('/api/v1/account/', data={'format': 'json'})
self.assertEqual(resp.status_code, status.HTTP_401_UNAUTHORIZED)
client.credentials(HTTP_AUTHORIZATION='JWT ' + token)
resp = client.get('/api/v1/account/', data={'format': 'json'})
self.assertEqual(resp.status_code, status.HTTP_200_OK)
私は同様の問題を抱えていましたが、比較するより多くのコード(tests.py)を用意するために私の解決策をお送りしました。
from Django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from Django.contrib.auth.models import User
class AuthViewsTests(APITestCase):
def setUp(self):
self.username = 'usuario'
self.password = 'contrasegna'
self.data = {
'username': self.username,
'password': self.password
}
def test_current_user(self):
# URL using path name
url = reverse('tokenAuth')
# Create a user is a workaround in order to authentication works
user = User.objects.create_user(username='usuario', email='[email protected]', password='contrasegna')
self.assertEqual(user.is_active, 1, 'Active User')
# First post to get token
response = self.client.post(url, self.data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK, response.content)
token = response.data['token']
# Next post/get's will require the token to connect
self.client.credentials(HTTP_AUTHORIZATION='JWT {0}'.format(token))
response = self.client.get(reverse('currentUser'), data={'format': 'json'})
self.assertEqual(response.status_code, status.HTTP_200_OK, response.content)