Search code examples
pythondjangodjango-testing

Failed lookup for key [user] in <User: test> exception when unit testing


I have an app that can send/cancel/accept/delete friend requests and I am trying to test it, however when I'm accepting a friend request and adding users to each others friends lists I am getting a Failed lookup for key [user] in <User: test> exception.

In my test I create a friend request object and send an accept get request to the view which should add each one of the users to each one of their friends lists and delete the friend_request.

Debugging shows that the error happens after this line in the view: user1.friends.add(user2), so essentially user2 is being added to user1 friends list but adding user1 to user2 friends list throws the exception that was mentioned above.

models.py

class User(AbstractBaseUser, PermissionsMixin):
    name = models.CharField('Full Name', max_length=35, unique=True, 
                                                        null=False, 
                                                        blank=False)
    friends = models.ManyToManyField("User", blank=True)

    def __str__(self):
        return self.name

class FriendRequest(models.Model)
    to_user = models.ForeignKey(User, related_name='to_user',
                                      on_delete=models.CASCADE)
    from_user = models.ForeignKey(User, related_name='from_user',
                                        on_delete=models.CASCADE)

views.py

from django.db import transaction

def accept_friend_request(request, pk):
    try:
        with transaction.atomic():
            from_user = User.objects.get(pk=pk)
            f_request = FriendRequest.objects.filter(
                from_user=from_user,
                to_user=request.user
            ).first()
            user1 = f_request.to_user
            user2 = from_user
            
            user1.friends.add(user2)
            print(user1.friends.all())
            
            user2.friends.add(user1)
            print(user2.friends.all())
            
            f_request.delete()
            return redirect(request.get_full_path())

    except Exception as ex:
        print(ex)
    return HttpResponse('User does not exist')

Here I am using the transaction.atomic() to prevent the exception from breaking the unittest transaction.

tests.py

def setUp(self):
    self.client = Client()
    self.user = User.objects.create_user(email='[email protected]', 
                                         name='test', 
                                         password='test')
    self.user1 = User.objects.create_user(email='[email protected]', 
                                          name='test1', 
                                          password='test1')
    self.client.force_login(self.user)

def test_accept_friend_request(self):
    friend_request = FriendRequest.objects.create(from_user=self.user1, 
                                                  to_user=self.user)
    self.client.get(reverse('accept_friend_request', 
                             kwargs={'pk': self.user1.pk}), follow=True)
    self.assertIn(self.user, self.user1.friends.all())
    self.assertIn(self.user1, self.user.friends.all())

Here is the result of running the test: (You can also see the result of the first print statement and the exception being printed)

Ran 1 test in 1.266s

FAILED (failures=1)
Destroying test database for alias 'default'...
System check identified no issues (0 silenced).
<QuerySet [<User: test1>]>
Failed lookup for key [user] in <User: test>

UPDATE

changing Exception to IntegrityError resulted in the following error:

raise VariableLookupError(django_elasticsearch_dsl.exceptions.VariableLookupError:
Failed lookup for key [user] in <User: test>

looks like elasticsearch-dsl has something to do with the exception here.

UPDATE

When debugging exception message changes to

Failed lookup for key [name] in <FriendRequest: FriendRequest object (1)>

Solution

  • So I finally managed to make it run correctly by changing the redirect to request.META.get('HTTP_REFERER', '/'), looks like it had problems with redirect looping.