So in a DeleteView, the GET request returns a confirmation page, and a simple POST request with no fields except for the csrf_token
actually gets the DeleteView to delete the object, upon which the user gets redirected to the success_url
.
How can I test this functionality? In my myclass_confirm_delete.html
file, I basically have:
<form action="{% url 'remove_myclass' object.id %}" method="post">
{% csrf_token %}
<p>Are you sure you want to remove {{ object.name }}?</p>
<input type="submit" value="Yes" class="btn btn-primary" />
</form>
where {% url 'remove_myclass' object.id %}
is the URL of the same exact page. It works in my browser. When I click "Yes," it redirects me to the success page, and the myclass
object is removed from the database.
Now I am trying to test this automatically with unit tests. I basically try
response = self.client.get(reverse('remove_myclass', args=(myobject.id,)), follow=True)
self.assertContains(response, 'Are you sure you want to remove') # THIS PART WORKS
self.client.post(reverse('remove_myclass', args=(myobject.id,)), follow=True)
self.assertRedirects(response, reverse('myclass_removed'), status_code=302) # FAILS; status code is 200
If I try print response
, I get the same exact response as when I had used the GET request.
It seems like while unit testing, no matter what kind of data I try to send in the POST request, it still gets treated as a GET request...
My class-based view:
class MyclassDelete(DeleteView):
model = myclass
success_url = '/myclass-removed/'
Any ideas?
Yeah, this is because you're forgetting to assign the post
request to response
, so you're checking the same response twice.
response = self.client.get(reverse('remove_myclass', args=(myobject.id,)), follow=True)
self.assertContains(response, 'Are you sure you want to remove') # THIS PART WORKS
post_response = self.client.post(reverse('remove_myclass', args=(myobject.id,)), follow=True)
self.assertRedirects(post_response, reverse('myclass_removed'), status_code=302)
This should do the trick.
Also, just a tip, trying to assert more than once per unit test is considered bad practice when unit testing. Instead try to break it up so that one test tests the GET
and on test tests the POST
.
from django.test import TestCase
class TestDifferentRequestMethods(TestCase):
def test_my_get_request(self):
response = self.client.get(reverse('remove_myclass', args=(myobject.id,)), follow=True)
self.assertContains(response, 'Are you sure you want to remove') # THIS PART WORKS
def test_my_post_request(self):
post_response = self.client.post(reverse('remove_myclass', args=(myobject.id,)), follow=True)
self.assertRedirects(post_response, reverse('myclass_removed'), status_code=302)
This makes for easier debugging and could save sometimes when stumbling onto these kinds of troubles!
UPDATE realized that I hadn't completed with a nice class to encompass the tests.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With