【问题标题】:How to test the result of catching an exception in python / django view如何在 python/django 视图中测试捕获异常的结果
【发布时间】:2018-10-17 09:50:28
【问题描述】:

给定一个视图,该视图使用以下代码从具有两个字段的'unique_together' 的模型创建对象:

    def form_valid(self, form):
        field1 = form.cleaned_data['field1']
        field2 = form.cleaned_data['field2']
        try:
            TheModel.objects.create(org=self.request.org, field1=field1, field2=field2)
        except IntegrityError as e:
            if 'UNIQUE constraint' in e.message:
                messages.error(self.request, _('field1 already exists.'))
            return super(ModelFormMixin, self).form_valid(form)
        messages.success(self.request, _('Fields have been successfully updated.'))
        return super(ModelFormMixin, self).form_valid(form)

我如何对'unique_together' 抛出错误时显示错误消息进行单元测试?

我当前的测试抛出了TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

这是当前的测试:

    @patch.object(messages, 'error')
    def test_error_handling(self, error_mock):

        TheModel.objects.create(org=self.org, field1='somepath', field2='anotherpath2')

        with transaction.atomic():
            response = self.client.post(reverse('configurations.create_amodel', args=(self.org.slug,)),
                {'field1': 'somepath', 'field2': 'anotherpath'}, follow=True)
            self.assertTrue(error_mock.called)

我不知道如何进行测试(测试捕获异常时运行的代码)

这是我的表单类:

class RedirectForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
    self.request = kwargs.pop('request', None)
    super(RedirectForm, self).__init__(*args, **kwargs)

field1 = forms.CharField(label='field1', required=True)
field2 = forms.CharField(label='field2', required=True)

class Meta:
    model = TheModel
    fields = ('field1', 'field2')

【问题讨论】:

  • 这整个方法很奇怪。与其尝试创建对象并捕获完整性异常,不如使用模型表单,它会知道 unique_together 属性并在验证时报告错误
  • 我正在使用一个modelForm(我没有发布整个视图,但是一个modelForm被导入到视图中来组成表单)。模型表单不创建对象 - 那么它如何验证对象是否已存在于数据库中?据我所知,模型表单只存在于前端,不做数据库验证,但也许我错了?
  • 重点是,模型表单创建对象,进行数据库验证。我不明白你说的只住在前端是什么意思。
  • 深入了解modelForms,似乎有开箱即用的数据库验证。我相信form_valid(在视图中)是modelForm的验证序列。意义——这是做事的正常方式。您还会在哪里调用自定义消息来表示成功和错误?

标签: python django django-models django-forms django-testing


【解决方案1】:

我发现通过在测试类中使用“TransactionTestCase”而不是“TestCase”可以避免在模型中调用异常的整个问题:

I.E.

class CreateRedirectViewTests(TransactionTestCase):

在调用unique_together 异常时发布错误消息的测试可以通过以下方式完成:

@patch.object(messages, 'error')
def test_error_message(self, error_mock):

    self.client.post(reverse('configurations.create_amodel', args=(self.org.slug,)),
            {'field1': 'somepath', 'field2': 'anotherpath'}, follow=True)

    self.client.post(reverse('configurations.create_amodel', args=(self.org.slug,)),
            {'field1': 'somepath', 'field2': 'anotherpath'}, follow=True)
    self.assertTrue(error_mock.called)

【讨论】:

    【解决方案2】:

    您可以从响应上下文中获取消息,然后检查您的错误。

    messages = list(response.context['messages'])
    self.assertEqual(len(messages), 1)
    self.assertEqual(str(messages[0]), 'field1 already exists.')
    

    您可以在这里阅读更多内容:How can I unit test django messages?

    【讨论】:

    • 我对消息进行单元测试没有问题。我已经通过模拟成功方法对成功消息进行了单元测试:@patch.object(messages, 'success') 问题在于异常
    猜你喜欢
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多