Форма действительна в модульном тесте, даже если ValidationError был поднят
Я проверяю свое представление на обработку недопустимых данных формы. В моем тестовом случае я отправляю форму с отсутствующим полем и ожидаю, что view обработает его, отобразив сообщение об ошибке. Вот соответствующий фрагмент из clean
в моей форме:
Форма:
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
всегда поднимается, однако, form.is_valid()
возвращает True
Тем не менее:
Вид:
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.
Это приводит к провалу теста, так как я утверждаю, что проверка формы не будет выполнена:
Тестовый Случай:
def test_invalid_data(self):
formdata = {
'first_name': 'Bruno',
'last_name': '', # Missing data.
'email': 'bruno@schulz.pl',
'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'])
Форма проверка корректно работает на реальном сервере (тестируется "вручную").
Похоже, что ValidationError
игнорируется во время оценки TestCase
.
* тестовый вывод:
.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'
2 ответа:
Вы не показали свой полный вид, но обычно вы это делаете
return redirect('/success-url/')
после успешного сообщения. Если ошибка проверки была проигнорирована, то представление будет перенаправлено с кодом состояния 302, и тест завершится неудачей в предыдущей строкеself.assertEqual(response.status_code, 200)
Вы можете получить доступ к форме из представления с помощью
Ваша проблема заключается в том, что ваши проверки не проверяют то, что вы думаете. При проверке форма модели, экземпляр модифицирован. Если вы хотите проверить, был ли пользователь изменен в базе данных, вам нужно сначала обновить его из базы данных.form = response.context['form']
. Если вы проверитеform.is_valid()
илиform.errors
в своем тесте, вы увидите, что вашValidationError
не был проигнорирован.self.user.refresh_from_db()
Попробуйте использовать
self.add_error('last_name', your_validation_error)
вместо того, чтобы просто вызывать ошибку:def clean(self): first_name = self.cleaned_data.get('first_name', '') last_name = self.cleaned_data.get('last_name', '') if not first_name: print('Form is invalid: missing first name') # define but don't raise the error missing_first_name = ValidationError('First name field is required.') self.add_error('first_name', missing_first_name) if not last_name: print('Form is invalid: missing last name') # define but don't raise error missing_last_name = ValidationError('Last name field is required.') self.add_error('last_name', missing_last_name) # you could also add a string instead of an Error, but a ValidationError is recommended: # self.add_error('last_name', 'the last name field is missing') # other stuff
Теперь
form.is_valid()
вернет False.Этот так называемый ответ привел меня к решению, и вот документы add_error. Вы должны добавить ошибку в форму с помощью
self.add_error
, а не вызывать ошибку проверки.(я нашел этот пример в docs , где ошибка возникает вместо того, чтобы передаваться в
self.add_error
, что может быть источником вашей путаницы, но это было для очистки конкретного поле. Это был не методform.clean()
. Я предполагаю, что вы могли бы поймать эту ошибку, а затем добавить ее сself.add_error
... но это уже другая проблема, которую нужно решить. Дело в том, что я не видел примеров в документах, гдеform.clean()
должен вызывать ValidationError. Вместо этого он должен добавить его в форму.)