How to write unit test for user-detail with router.register base name

Question:

This error appears when I write a test for user-detail, I thought the error from response = self.client.get(reverse('user-detail',kwargs={'pk':1})), I used router.register to config ulrs base name, and that makes me confused when writing the test. So in this case, where the point in my code was wrong?

    def test_list_user_detail(self):
        """
            List user detail
        """
        self.client.post(self.url, self.data, format='json')
        resp = self.client.post(
            '/auth/token/login/', data={'email': '[email protected]', 'password': 'Boo'}, format='json')
        token = resp.data['auth_token']
        self.client.credentials(HTTP_AUTHORIZATION='token '+token)

        response = self.client.get(reverse('user-detail',kwargs={'pk':1}))
        print(response.data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
======================================================================
FAIL: test_list_user_detail (sellHouse.tests.UserTest)
List user detail
----------------------------------------------------------------------
Traceback (most recent call last):
  File "D:coderestfullapiexamplesellHousetests.py", line 68, in test_list_user_detail
    self.assertEqual(response.status_code, status.HTTP_200_OK)
AssertionError: 404 != 200

----------------------------------------------------------------------

Try print response.data : {'detail': ErrorDetail(string='Not found.', code='not_found')}

Asked By: Huy Nguyen

||

Answers:

fixed, because I wrote 2 test cases above, in each test case include creating a user, so the pk id for this test should be = 3

Answered By: Huy Nguyen

You can not rely on the primary key value dispatch by the database. Tests can run in any order, and any subset of tests can run. Therefore it is possible that sometimes it is 3 whereas when you run the tests in a different order, or only a subset of the tests, it is 1. Therefore you should work with the primary key of your database object, so for example:

from django.test import TestCase

class MyTestCase(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            email='[email protected]', password='Boo'
        )

    def test_list_user_detail(self):
        """
            List user detail
        """
        self.client.post(self.url, self.data, format='json')
        resp = self.client.post(
            '/auth/token/login/', data={'email': '[email protected]', 'password': 'Boo'}, format='json')
        token = resp.data['auth_token']
        self.client.credentials(HTTP_AUTHORIZATION='token '+token)

        response = self.client.get(reverse('user-detail',kwargs={'pk': self.user.pk}))
        print(response.data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

Here we thus assign the created object to self.user, and then use self.user.pk when we determine the URL.

Answered By: Willem Van Onsem