1

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?

  • Can you show your `setUp`? The error you get is saying there is no logged in user yet. – Brian Destura Jul 07 '21 at 00:14
  • def setUp(self): self.user = CustomUser.objects.create( username='testUser', email='test@email.com', password='secret' ) Cart.objects.create(owner=self.user) self.product = Product.objects.create( name='testProduct', price=2.50, category='testCategory', quantity=10, shipping='standard', seller=self.user, on_sale=False, is_featured=False, ) [...] – damonmickelsen Jul 07 '21 at 02:37
  • [...] self.user.cart.products.add(self.product, through_defaults={'product_quantity': 1}) self.cart_product = CartProduct.objects.get(cart=self.user.cart, product=self.product) – damonmickelsen Jul 07 '21 at 02:37
  • I also tried with the line "self.client.user = self.user" in the setUp function and it still threw the error at me. – damonmickelsen Jul 07 '21 at 02:41

1 Answers1

0

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='test@email.com', 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

Brian Destura
  • 11,487
  • 3
  • 18
  • 34
  • Same error. For some reason, it's not looking at the CustomUser model, but instead the AnonymousUser model. – damonmickelsen Jul 07 '21 at 02:50
  • Am I correct that creating self.client is "self.client = Client()" after importing "from django.test import Client"? – damonmickelsen Jul 07 '21 at 02:57
  • Yes. I updated my answer with another required change for password. You need to properly set the password when you create the user by using `set_password` and then saving it again (to properly hash the password). Then call `client.login` as is. Also make sure that you use the correct username based on what `USERNAME_FIELD` is set in your `settings`. – Brian Destura Jul 07 '21 at 03:51
  • 1
    Nice. That was it. `self.user.set_password('secret)` followed by a `self.user.save()` got the login to return `True` Now I need to sort out my response status_code values. Thanks for the help! – damonmickelsen Jul 07 '21 at 21:50
  • No worries! Please do accept this answer if it solved your problem. – Brian Destura Jul 07 '21 at 23:46