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
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()
...
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() )
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
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()
...
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() )