Search code examples
djangoforeign-keysdjango-testsdjango-custom-userabstractuser

How do I run Django test using a CustomUser(AbstractUser) class instead of default AbstractUser for correct ForeignKey assignment during test?


I have a CustomUser model in 'accounts' app that overrides Django's default auth.User:

class CustomUser(AbstractUser):
    age = PositiveIntegerField(null=True, blank=True)
    user_type = CharField(max_length=8, null=False, choices=[('customer', 'Customer'), ('owner', 'Owner')])

And another app 'ecommerce' with a model Product (abbreviated for brevity) with a ForeignKey to the CustomUser field above:

class Product(Model):
    name = CharField(max_length=255, null=False, blank=False)
    [...]
    seller = ForeignKey(CustomUser, on_delete=CASCADE, related_name='products')

When I create the new Product, I'm using form_valid() function on the model to set the user based on the request that Django uses via CreateView. This works when I'm working in a browser, however does not when I am trying to validate my ProductCreateView through a test a script:

views.py

class ProductCreateView(CreateView):
    model = Product
   [...]

    def form_valid(self, form):
        form.instance.seller = self.request.user
        return super().form_valid(form)

test.py

    def test_product_create_view(self):
        response = self.client.post(
            reverse('ecommerce_post_product'), {
                'name': 'newProduct', 'price': 2.99, 'category': 'newCategory',
                'quantity': 100, 'shipping': 'standard',
            }) # error happens here
        self.assertEqual(response.status_code, 302) # test does not reach this line

When I run my tests, this test always throws an error stating, ValueError: Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x7fbce54f0040>>": "Product.seller" must be a "CustomUser" instance."

I have tried passing in the self.user that I defined in the 'setUp()' function of the TestCase with a line self.client.user = self.user, but it continues to throw the error.

How do I get my test to pass in a CustomUser instead of the AnonymousUser that it is using when running the script?


Solution

  • You are getting AnonymousUser because there is no user logged in when you access the view. In your setUp(), create the user making sure you hash the password properly. Then call client.login with the credentials:

    def setUp(self): 
        self.user = CustomUser.objects.create(username='testUser', email='[email protected]', password='')
        self.user.set_password('secret')
        self.user.save()
        ...
        self.client = Client()
        self.client.login(username='testUser', password='secret')
    

    You can read more about what's going on with these changes here