Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Custom User Manager Unit Test - NoneType object is not callable

This all started when I downloaded coverage.py and started testing my django project. Everything is fine, however I'm lacking coverage on a custom user manager I set up in Models.py

Here's the full code.

models.py

from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models
from django.utils.translation import ugettext_lazy as _

class UserManager(BaseUserManager):
    """Define a model manager for User model with no username field."""

    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """Create and save a User with the given email and password."""
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)

        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        """Create and save a regular User with the given email and password."""
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        """Create and save a SuperUser with the given email and password."""
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)


class CustomUser(AbstractUser):
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)
    # profile_image = models.ImageField(upload_to="users/profile_pic", blank=True)
    is_pastor = models.BooleanField(default=True)
    home_church = models.ForeignKey(
        'church.Church',
        on_delete="CASCADE",
        blank=True,
        null=True)

    username = None
    email = models.EmailField(_('email address'), unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager() ## This is the new line in the User model. ##

I'm attempting to test the "_create_user" function in the UserManager. Here is my code

test.py

class UserManagerTestCase(TestCase):

def test_main_create_user(self):
    manager = UserManager()
    user = manager._create_user('[email protected]', 'password123')
    self.assertTrue(isinstance(user, User))

Unfortunately, when I call the '_create_user' function I get a Type Error: 'NoneType' object is not callable.

This is strange, because the model manager works as expected when creating users and I confirmed with print statements that both the email and **extra_fields arguments are not None.

Some research online said this might because the Manager is not designed to be called directly. Is that the case? If so, how should you handle unit testing?

like image 992
Jon Hrovat Avatar asked Oct 15 '25 04:10

Jon Hrovat


1 Answers

Instantiate CustomUser() with values so it can be used to access the methods to be tested. UserManager CANNOT be used directly, it is only accessible through the Model it was created for: CustomUser.

#tests.py
class UserManagerTestCase(TestCase):
    def test_main_create_user(self):
        user = CustomUser.objects.create_user('[email protected]', 'password123')
        self.assertTrue(isinstance(user, User))
like image 130
Staccato Avatar answered Oct 20 '25 10:10

Staccato



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!