问题
I'm having problem authenticating with my Django Rest Framework API in Unit Unit Tests. The system works as expected when accessing it through the browser. I however receive a 401 HTTP status when sending a put request to the following class at the following endpoint:
class UserDetail(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet):
authentication_classes = (BasicAuthentication, TokenAuthentication)
permission_classes = IsAuthenticated,
queryset = CustomUser.objects.all()
serializer_class = UserSerializer
The test below is as follows:
class AccountTests(APITestCase):
def setUp(self):
self.user = CustomUser.objects.create_user(email="user1@test.com", password="password1", is_staff=True)
self.user.save()
self.user = CustomUser.objects.get(email="user1@test.com")
self.client = APIClient()
def test_add_name(self):
self.client.login(email="user1@test.com", password='password1')
url = reverse('customuser-detail', args=(self.user.id,))
data = {'first_name': 'test', 'last_name': 'user'}
self.client.login(email="user1@test.com", password='password1')
response = self.client.put(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
When printing the response.data, I receive:
{u'detail': u'Authentication credentials were not provided.'}
The client.login(...) method returns true, but the credentials do not appear to be attached to the header. My experiments in the IsAuthenticated permission classes had an request.user = AnonymousUser. In the BasicAuthentication class, auth = None.
Am I missing something as regards to using BasicAuth in settings.py? Or even in the test itself?
Thanks.
回答1:
First, {u'detail': u'Authentication credentials were not provided.'}
occurs when the credential that you "provide" doesn't match with models. (I think it is bad error message)
So, you should set user's password by set_password()
method, because of encryption.
self.user = CustomUser.objects.create_user(email="user1@test.com", is_staff=True)
self.user.set_password("password1")
self.user.save()
or, you can use force_login()
for testing.
self.client.force_login(
user=User.objects.first(),
backend='django.contrib.auth.backends.ModelBackend' # one of your AUTHENTICATION_BACKENDS
)
回答2:
You may need to use force_authenticate()
method for logging in,
def test_add_name(self):
self.client.force_authenticate(self.user)
........
You may consider re-writing your test-case, maybe somewhat like this,
class AccountTests(APITestCase):
def setUp(self):
self.user = CustomUser.objects.create_user(email="user1@test.com", password="password1", is_staff=True)
self.client = APIClient()
def test_add_name(self):
self.client.force_authenticate(self.user)
url = reverse('customuser-detail', args=(self.user.id,))
data = {'first_name': 'test', 'last_name': 'user'}
response = self.client.put(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
来源:https://stackoverflow.com/questions/37513050/django-apiclient-login-not-working