I'm testing my view for handling invalid form data. In my test case I'm submitting form with missing field and expect view to handle it by displaying error message. Here is a relevant snippet from clean
in my form:
def clean(self):
first_name = self.cleaned_data.get('first_name', '')
last_name = self.cleaned_data.get('last_name', '')
if not first_name or not last_name:
print('Form is invalid')
# This is always executed.
raise ValidationError('All fields are required.')
# other stuff
ValidationError
is always raised, however, form.is_valid()
returns True
nonetheless:
form = forms.EditProfileForm(request.POST, instance=user)
if form.is_valid():
print('Form is valid')
# Update user data.
# Always executed even though error was raised.
This leads to test failing, since I'm asserting that form validation will fail:
def test_invalid_data(self):
formdata = {
'first_name': 'Bruno',
'last_name': '', # Missing data.
'email': '[email protected]',
'password': 'metamorphosis'
}
request = self.factory.post('/accounts/profile', formdata)
request.user = self.user
setup_messages(request)
response = ProfileView.as_view()(request)
self.assertEqual(response.status_code, 200)
self.assertNotEqual(self.user.first_name, formdata['first_name']) # Fails.
self.assertNotEqual(self.user.last_name, formdata['last_name'])
self.assertNotEqual(self.user.email, formdata['email'])
self.assertNotEqual(self.user.username, formdata['email'])
Form validation works properly on a live server (tested "by hand").
It looks like ValidationError
is ignored during TestCase
evaluation.
.Form is invalid
F..Form is valid
.
======================================================================
FAIL: test_invalid_data (.tests.ProfileTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/apps/accounts/tests.py", line 114, in test_invalid_data
self.assertNotEqual(self.user.first_name, formdata['first_name'])
AssertionError: 'Bruno' == 'Bruno'
You haven't shown your full view, but usually you do return redirect('/success-url/')
after a successful post. If your validation error was ignored, then the view would redirect with status code 302, and your test would fail on the earlier line self.assertEqual(response.status_code, 200)
You can access the form from the view with form = response.context['form']
. If you check form.is_valid()
or form.errors
in your test, you will see that your ValidationError
has not been ignored.
Your issue is that your assertNotEqual
checks are not testing what you think they are. When you validate a model form, the instance is modified. If you want to check whether the user has been modified in the database, you need to refresh it from the database first.
self.user.refresh_from_db()