How to test save Django model method with pytest?

Viewed 501

What I have

I've overwritten the save method of my User model to be able to change the first and last name with the first letter in capital.

User model

from django.contrib.auth.models import AbstractBaseUser

class User(AbstractBaseUser):
    name = models.CharField(
        verbose_name=_("Name"),
        max_length=30,
    )
    last_name = models.CharField(
        verbose_name=_("Last Name"),
        max_length=50,
    )
    # ...other fields

    def save(self, *args: Any, **kwargs: Any) -> None:
        """Always have the name and last_name first letter in uppercase"""
        for field_name in ["name", "last_name"]:
            val = getattr(self, field_name, False)
            if val:
                setattr(
                    self,
                    field_name,
                    string.capwords(val.lower()),
                )
        super(User, self).save(*args, **kwargs)

I'm using pytest and factory_boy to test my models. First I've created a Factory to create users:

Factory

from factory import DjangoModelFactory, Faker

class UserFactory(DjangoModelFactory):
    """Define User Factory"""

    name = Faker("first_name", locale="es")
    last_names = Faker("last_name", locale="es")
    # ...other fields

    class Meta:
        model = get_user_model()

I make my factory available for all my tests by putting it in a fixture in conftest.py:

from app_name.users.tests.factories import UserFactory

@pytest.fixture
def user() -> User:
    """Create user for testing."""
    return UserFactory()

The problem

I want to test my save method but when I try to access my user's name or last_name fields in the test it already comes with the first letter capitalized. I would like to get the raw data before the save method is applied in order to perform the test.

import pytest

pytestmark = pytest.mark.django_db


def test_save(user: User):
    print(user.names) # -> comes with the changes applied to the save method
    print(user.last_names) # -> comes with the changes applied to the save method
1 Answers

You don't need to get the raw data before the save method is applied. Actually you are testing it already! Because the factory saves the objects, so you can just check whether it has been properly edited names or not.

Something like this:

>>> name = user.name
>>> expected_name = string.capwords(name.lower())
>>> assert name == expected_name, "name is not correct"
Related