0

I want to test a post request for a route with authentication required(Knox from Django Rest Framework). Here the post request should object for a logged in user.

Following is urls.py

path('cards', addCard.as_view(), name="cards"), 

Following is addCard view

class addCard(generics.ListCreateAPIView): serializer_class = CardSerializer permission_classes = [permissions.IsAuthenticated, IsOwnerOrNot] def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) card = serializer.save(owner=self.request.user) return Response({'card': CardSerializer(card, context=self.get_serializer_context()).data,}) def get_queryset(self): return self.request.user.cards.order_by('-id') 

Following is the test case, I used this answer, I got 401!=201 error, clearly Unauthorized user.

class addCardAPIViewTestCase(APITestCase): url = reverse("cards") def setUp(self): self.username = "john" self.email = "[email protected]" self.password = "you_know_nothing" self.user = get_user_model().objects.create_user(self.username, self.password) self.token = Token.objects.create(user=self.user) def test_create_cards(self): client = APIClient() client.login(username=self.username, password=self.password) client.credentials(HTTP_AUTHORIZATION='Token ' + self.token.key) response = client.post(self.url,{ "bank": "Citibank", "card_number": "5618073505538298", "owner_name": "c1", "cvv": "121", "expiry_date_month": "03", "expiry_date_year": "2023" },format='json') self.assertEqual(response.status_code, 201) 
4
  • client.credentials(HTTP_AUTHORIZATION='Token ' + self.token.key). Doesn't this line set authentication header? Commented Apr 5, 2021 at 6:14
  • Yes, while checking from POSTMAN, we insert Authentication Header with a Token, I believe this is how I handled here to authenticate user, correct me If I am wrong. I am open to suggestions, if there is any alternative way to test a POST request which requires login, in my case only username and password. Commented Apr 5, 2021 at 6:19
  • just remove client.login and client.credentials lines for testing unauthorized user and it should return 401 Commented Apr 5, 2021 at 6:21
  • Yes, it returns 401 after removing client.login, client.credentials, I wanted to make a successful POST hence 201 is required. Commented Apr 5, 2021 at 6:27

2 Answers 2

1

Use client.force_authenticate(...)

class addCardAPIViewTestCase(APITestCase): # Rest of your code def test_create_cards(self): self.client.force_authenticate(self.user) response = self.client.post(self.url, { "bank": "Citibank", "card_number": "5618073505538298", "owner_name": "c1", "cvv": "121", "expiry_date_month": "03", "expiry_date_year": "2023" }, format='json') self.assertEqual(response.status_code, 201)
Sign up to request clarification or add additional context in comments.

Comments

0

You can use client.login OR client.credentials if you want to test for authenticated user. The first one should be used if you authenticate users via rest_framework.authentication.SessionAuthentication (also consider client.force_login for better performance) and second one for token authentication. Using both of them at the same time is meaningless.

1 Comment

I tried using them separately, one at a time, still getting 401. I used self.client.force_authenticate(self.user) as suggested by @JPG and it worked.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.