djangodjango-rest-frameworktestcasedjango-viewsets

Django TestCase slef.client.patch gives a 404 error


I want to test the update function of a view set

from rest_framework.viewsets import ModelViewSet
@extend_schema(tags=['Customers'])
class CustomerViewSet(ModelViewSet):
    """ This view can be used to see all the customers"""
    serializer_class = CustomerSerializer
    .....
    def update(self, request, *args, **kwargs):
        return self._update_customer(request, *args, **kwargs)

The route is mapped here (like the other view sets):

router.register(r'customers', CustomerViewSet, basename='customer')

Like for my other view sets where it works, i test the update method by resolving it in my test case

from django.test import TestCase
from rest_framework.reverse import reverse
......
class CustomerUpdateViewTest(TestCase):
         .....
         def test_customer_missing(self):
             url = reverse('customer-detail', [2])        
             token = create_access_token(self.my_user)

             data = {
               'customer': 'new name customer'
             }

             response = self.client.patch(url, data, 
                content_type="application/json",
                HTTP_AUTHORIZATION=f'Bearer {token}')

I have created before in a setup method many customers But the self.client.patch instruction give always a 404 error

In my running application, the path is /api/customers/x (like in my test where x = a customer identifier) and is an HTTP PATCH verb

For my similar views, i test in a very similar way and it works.

When i give a wrong token, i have a 401 error, which indicate to my point of view that the url is correct.

Do you have already encountered such a problem ? If yes, what can i do to solve this problem ?


Solution

  • The problem was the user with which I call the endpoint.

    In the Django code (models) the user is of type:

    from django.contrib.auth.models import AbstractUser
    class User(AbstractUser)
    

    This user has the attribute is_superuser = False, but I called the endpoint with a user that is not super user. Calling the endpoint with a user that has the attribute is_superuser = True will succeed.

    It was for me a little bit tricky because the 404 error is to my point of view not a true one. This 404 error hides a problem of authorization for a user that is not super user (or has not the permission to change the customer). I obtain the same error if I use in the reverse a pk value that does not exist for a customer. For example, as I use:

    url = reverse('customer-detail', [2]) 
    

    if I do not have a customer whose the pk value = 2, then I get a 404 error too.

    Consequently, I use a super user to call the endpoint and also replace the existing reverse code by the following (with an existing pk for the customer):

    url = reverse('customer-detail', [self.customer_to_test.pk])