Search code examples
djangodjango-rest-frameworkdjango-testing

AttributeError: 'CustomUser' object has no attribute 'items' - Unit Test Phase


I am working on a book project. For this project, I have been already created a custom user model and using it. However, today I tried to test this model. When I want to run this code, it returns AttributeError: 'CustomUser' object has no attribute 'items' response.

I don't understand where am I doing wrong. If I send the data in dictionary type, the test works, but if I want to send in instance type, it returns the error.

Traceback

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
E
======================================================================
ERROR: test_user_registration (account.tests.custom_user_tests.CustomUserRegistrationTests)
User registration with correct values
----------------------------------------------------------------------
Traceback (most recent call last):
  File "E:\!Staj\bookorbooks\bookorbooks\account\tests\custom_user_tests.py", line 35, in test_user_registration
    response = self.client.post(self.url, self.user1)
  File "E:\!Staj\bookorbooks\env\lib\site-packages\rest_framework\test.py", line 295, in post
    response = super().post(
  File "E:\!Staj\bookorbooks\env\lib\site-packages\rest_framework\test.py", line 208, in post
    data, content_type = self._encode_data(data, format, content_type)
  File "E:\!Staj\bookorbooks\env\lib\site-packages\rest_framework\test.py", line 179, in _encode_data
    ret = renderer.render(data)
  File "E:\!Staj\bookorbooks\env\lib\site-packages\rest_framework\renderers.py", line 914, in render
    return encode_multipart(self.BOUNDARY, data)
  File "E:\!Staj\bookorbooks\env\lib\site-packages\django\test\client.py", line 245, in encode_multipart
    for (key, value) in data.items():
AttributeError: 'CustomUser' object has no attribute 'items'

----------------------------------------------------------------------
Ran 1 test in 0.159s

FAILED (errors=1)
Destroying test database for alias 'default'...

Custom User Model

class CustomUser(AbstractUser):
    GENDER_CHOICES = (
        (1, AccountStrings.CustomUserStrings.gender_choice_male),
        (2, AccountStrings.CustomUserStrings.gender_choice_female),
        (3, AccountStrings.CustomUserStrings.gender_choice_other),
    )

    USER_TYPE_CHOICES = (
        (1, AccountStrings.CustomUserStrings.user_type_choice_default),
        (2, AccountStrings.CustomUserStrings.user_type_choice_child),
        (3, AccountStrings.CustomUserStrings.user_type_choice_parent),
        (4, AccountStrings.CustomUserStrings.user_type_choice_instructor),
    )
    objects = CustomUserManager()
    email = models.EmailField(max_length=255,
                              unique=True,
                              null=False,
                              blank=False)
    identity_number = models.CharField(
        max_length=11,
        unique=True,
        verbose_name=AccountStrings.CustomUserStrings.
        identity_number_verbose_name)
    birth_date = models.DateField(
        null=True,
        blank=True,
        verbose_name=AccountStrings.CustomUserStrings.birth_date_verbose_name)
    gender = models.PositiveSmallIntegerField(
        choices=GENDER_CHOICES,
        default=1,
        verbose_name=AccountStrings.CustomUserStrings.gender_verbose_name)
    user_type = models.PositiveSmallIntegerField(
        choices=USER_TYPE_CHOICES,
        default=1,
        verbose_name=AccountStrings.CustomUserStrings.user_type_verbose_name)

    class Meta:
        verbose_name = AccountStrings.CustomUserStrings.meta_verbose_name
        verbose_name_plural = AccountStrings.CustomUserStrings.meta_verbose_name_plural

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

Unit Test

from rest_framework.test import APITestCase
from django.urls import reverse
from django.contrib.auth import get_user_model

User = get_user_model()


class CustomUserRegistrationTests(APITestCase):
    url = reverse("account:register")

    def setUp(self) -> None:
        self.user1 = User.objects.create_user(first_name="John",
                                              last_name="Doe",
                                              email="[email protected]",
                                              username="demo",
                                              password="Pas12wor21d",
                                              identity_number = "12345678910",
                                              user_type = "2",
                                              gender = 1)

    def test_user_instance(self):
        """
            Check the user instance was created successfully
        """

        self.assertIsInstance(self.user1, User)

    def test_user_registration(self):
        """
            User registration with correct values
        """

        data = {
            "username" : "johndoe",
            "email": "[email protected]",
            "password": "johndoe123",
            "identity_number": "12345678911",
            "user_type": 2,
            "gender": 1,
            "first_name": "John",
            "last_name": "Doe",
            "birth_date": "2000-07-26"
        }

        response = self.client.post(self.url, self.user1)
        # response = self.client.post(self.url, data)
        self.assertEqual(201, response.status_code)

Solution

  • In your test_user_registration test, you need to pass the data as second parameter of the POST request, so:

    #                      not self.user1  ↓
    response = self.client.post(self.url, data)

    By using self.user1, you used a CustomUser object, and since that is not a dictionary-like object, it will thus raise an error.