2017-08-10 7 views
2

無効なフォームデータを処理するビューをテストしています。私のテストケースでは、フィールドが欠落しているフォームを提出し、エラーメッセージを表示してビューを処理することを期待しています。ここに私のフォームでcleanから関連の抜粋です:ValidationErrorが発生してもユニットテストで有効なフォーム

フォーム:

ビュー:

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 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を上げていますフォームの検証が失敗すると主張しているので、テストに失敗します:

テストケース:

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']) 

フォームの検証は、( "手で" テスト)ライブサーバー上で正常に動作します。

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' 

答えて

1

あなたはあなたの完全なビューを示していないが、通常、あなたは成功した後の後return redirect('/success-url/')を行います。検証エラーが無視された場合、ビューは状態コード302でリダイレクトされ、以前の行でテストが失敗します。self.assertEqual(response.status_code, 200)

form = response.context['form']というビューからフォームにアクセスできます。テストでform.is_valid()またはform.errorsをチェックすると、ValidationErrorが無視されていないことがわかります。

あなたの問題は、お客様のassertNotEqual小切手が自分の考えをテストしていないことです。モデルフォームを検証すると、インスタンスが変更されます。ユーザーがデータベースで変更されているかどうかを確認するには、refresh it from the database firstが必要です。

self.user.refresh_from_db() 
+0

"ビューはステータスコード302 'でリダイレクトされます - Bingo、はい、このアサーションについて忘れてしまったのですが、' is_valid() 'ということが判明しました-branchは実際には実行されませんでした。私の説明ではほとんどのコードは省略していますが、ユーザーインスタンスは他のテストでも変更されていますので、それをリフレッシュせずに失敗しなければなりません。 'refresh_from_db'を適用すると問題が解決しました。 – Siegmeyer

-1

だけでエラーを発生させるのではなく、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を返します。

This SO answer私を解決に導いた。here are the add_error docs。検証エラーを発生させずに、self.add_errorという形式でエラーをフォームに追加する必要があります。

は(私はあなたの混乱の源となり得るエラーが発生代わりの self.add_errorに渡される this example in the docsを見つけたが、それは特定のフィールドを洗浄するためだった。そうではありませんでした form.clean()方法。私はあなたの可能性が想定しています問題を解決して self.add_errorを追加してください...それは解決する別の問題です。つまり、 form.clean()がValidationErrorを発生させるべきドキュメントの例は見当たりませんでした。)

関連する問題