【问题标题】:AssertionError: ValidationError not raised by full_cleanAssertionError:full_clean 未引发 ValidationError
【发布时间】:2020-05-15 16:06:57
【问题描述】:

在下面的表格中,我声明了一个 clean() 方法,它正在评估以下条件:

expiration_date 是否在 created_date 之前?

如果该条件为真,我想提出一个ValidationError。运行测试时,我收到以下错误:AssertionError: ValidationError not raised by full_clean

但是,如果调用 form.errors.as_data(),则会导致:{'expiration_date': [ValidationError(['The expiration date is set before the created date'])]}

能否解释一下发生了什么?

forms.py

class MenuForm(forms.ModelForm):
    MENU_YEARS = [2019, 2020, 2021]

    season = forms.CharField(
        min_length=4, 
        validators=[validate_season]
    )
    items = forms.ModelMultipleChoiceField(
        queryset=Item.objects.all(),
        to_field_name='name'
    )
    expiration_date = forms.DateTimeField(
        required=False,
        widget=SelectDateWidget(
            years=MENU_YEARS,
            empty_label=("Choose Year", "Choose Month", "Choose Day")
        )
    )

    def clean(self):
        cleaned_data = super().clean()
        created_date = cleaned_data['created_date'] = timezone.now()
        expiration_date = cleaned_data['expiration_date']
        if created_date > expiration_date:
            raise ValidationError(
               {'expiration_date': "The expiration date is set before the created date"}
            )

    class Meta:
        model = Menu
        fields = ['season', 'items', 'expiration_date']

test_forms.py

class TestMenuForm(TestCase):

    @classmethod
    def setUpTestData(cls):
        cls.data = {
            'season': 'Late Fall',
            'items': ['Crepe'],
            'expiration_date': datetime(2018, 1, 2)
        }

    def test_menu_model_clean(self):
        with self.assertRaises(ValidationError):
            self.menu_form.full_clean()

【问题讨论】:

  • 查看文档here,您将参数传递给ValidationError 的方式不是文档显示的内容。你有没有尝试遵循?如果需要导入_,请参阅stackoverflow.com/a/1962289/6388133
  • 我将验证错误修复为:ValidationError(_("Invalid Expiration"), code="invalid_expiration"),但我仍然遇到同样的错误。

标签: python django unit-testing django-forms


【解决方案1】:

需要返回清理后的数据

def clean(self):
    cleaned_data = super().clean()
    created_date = cleaned_data['created_date'] = timezone.now()
    expiration_date = cleaned_data['expiration_date']
    if created_date > expiration_date:
        raise ValidationError(
           {'expiration_date': "The expiration date is set before the created date"}
        )
    return cleaned_data

【讨论】:

    【解决方案2】:

    尽管@Marcell 的回答是有效的,但我认为这不是您所遇到行为的原因。

    据我所知,在 ModelForm 上调用 full_clean 时,也会调用 clean 方法,但 ValidationErrors 在内部被捕获,并且错误被添加到 form.errors。所以你的测试不会“看到”这个错误。这是您当前在测试中看到的内容。恕我直言,这种行为是有道理的,因为您可能不希望您的应用因验证错误而停止。

    要测试您的ValidationError,您可能需要直接调用表单clean 方法而不是full_clean

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-14
      • 2021-07-12
      • 1970-01-01
      相关资源
      最近更新 更多