Search code examples
djangopython-3.xdjango-rest-frameworkfactory-boy

Django [AssertionError: 401 != 201]


I'm writing tests for my API. Now i want to test post method.

Here's my views.py:

class TaskViewSet(viewsets.ModelViewSet):

    queryset = Task.objects.all()
    serializer_class = serializers.TaskSerializer
    authentication_classes = (BasicAuthentication,)
    permission_classes = (permissions.IsAuthenticated, permissions.IsAdminUser)

Here's my tests.py:

class UserFactory(DjangoModelFactory):

    class Meta:
        model = User

    username = 'dima'
    password = 'moonmvm2k14'
    email = '[email protected]'
    is_superuser = True
    is_active = True
    is_staff = True


class TaskFactory(DjangoModelFactory):

    class Meta:
        model = Task

    title = "TASK N1"
    description = "smth"
    person = factory.SubFactory(UserFactory)
    deadline = date.today()


class ViewTest(APITestCase):

    def setUp(self):
        self.task = TaskFactory()

        self.username = 'myuser'
        self.password = 'test' 
        self.email = '[email protected]'

        self.admin = User.objects.create_superuser(self.username, self.password, self.email)

        self.client = APIClient()
        self.client.login(username=self.admin.username, password=self.admin.password)

    def test_post_task(self):
        url = '/task-list/'
        json_tasks = serializers.TaskSerializer(self.task)
        data = json_tasks.data
        response = self.client.post(url, data)
        tasks_count = Task.objects.count()
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(tasks_count, 2)

But when i try to test it i see this error:

AssertionError: 401 != 201

I don't know why my test fails with Not Authorized Status Code.

So, what's the problem and how can I solve it?


Solution

  • The issue origins from the way you simulate login in the test case.

    You are using the login() method of the APIClient class, which is suitable when you have SessionAuthentication.

    From the docs:

    The login method is appropriate for testing APIs that use session authentication, for example web sites which include AJAX interaction with the API.


    But in your view you use BasicAuthentication (which is actually only suitable for testing purposes), so you may use another method of the client class - force_authenticate:

    class ViewTest(APITestCase):
        def setUp(self):
            ...
    
            self.client = APIClient()
            self.client.force_authenticate(user=self.admin)
    

    This would make your admin user actually logged in and the status code assert should pass successfully.