Форма действительна в модульном тесте, даже если 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. Вместо этого он должен добавить его в форму.)