Aditya Mahajan
Aditya Mahajan

Reputation: 315

To test a POST request for an authenticated route in Django Rest Framework

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)

Upvotes: 0

Views: 1412

Answers (2)

JPG
JPG

Reputation: 88499

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)

Upvotes: 1

Elgin Cahangirov
Elgin Cahangirov

Reputation: 2022

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.

Upvotes: 0

Related Questions