How to test delete instance in Django

Question:

Running Django, I have a view to delete logged-in user on POST request.

@login_required
def delete_user(request):
    """Delete user from DB."""
    if request.method == "POST":
        get_object_or_404(User, pk=request.user.pk).delete()
        messages.success(request, _("User deleted!"), extra_tags="success")
        return redirect("home")
    return render(request, "accounts/delete-user.html")

HTML form is:

            <form method="POST" name="delete-user-form" id="delete-user-form">
                {% csrf_token %}
                <button class="mt-4 btn btn-danger" name="delete-user-btn" id="delete-user-btn" type="submit">{% translate "Delete my profile" %}</button>
            </form>

My test class with user:

class ViewsWithLoggedInUserTest(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        User.objects.create_user(
            email="[email protected]",
            password="test",
            first_name="TestFirstName",
            last_name="TestLastName",
            hometown="Kiev",
            facebook_link="https://www.facebook.com/profile.php?id=1000",
            contacts="+380991111111",
            start_coordinates="50.45, 30.52",
            avatar="avatar/default_avatar.jpg",
        )
    def setUp(self):
        self.user = User.objects.get(email="[email protected]")
        self.client.force_login(user=self.user)
        print("setUp")

    def test_delete_user_post(self):
        """Test delete user post."""
        response = self.client.post(path=reverse("delete_user"))
        self.assertFalse(self.user)
        self.assertEqual(response.status_code, 302)
        self.assertRedirects(response, expected_url=reverse("home"))

I can not undrstand how to test this function, my test_delete_user_post gives me

AssertionError: <User: [email protected]> is not false
Asked By: Vitalii Mytenko

||

Answers:

It’s not working because the variable self.user still holds the previously assigned value.

Use the refresh_from_db() method to update the variable with fresh value.

Also, to test deletion, you have to test if the DoesNotExist exception is raised or not. Testing using assertFalse will not work.

Code example:


def test_delete_user_post(self):
        response = self.client.post(path=reverse("delete_user"))
        
        with self.assertRaises(User.DoesNotExist):
            # Django will try to fetch the new value from the database
            # but since it's been deleted, DoesNotExist exception
            # will be raised
            self.user.refresh_from_db()

        ...


Answered By: xyres

A (less complex/ more obvious?) alternative to xyres’ answer

# setUp created self.user which this test should delete ...
def test_delete_user_post(self):
    response = self.client.post(path=reverse("delete_user"))
    self.assertFalse( User.objects.filter( pk=self.user.pk).exists() )
Answered By: nigel222
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.