【问题标题】:Testing Django view: how can we know if catched exception was actually raised?测试 Django 视图:我们如何知道是否确实引发了捕获的异常?
【发布时间】:2018-01-22 13:36:57
【问题描述】:

我想测试我的视图中的异常是否在预期时引发。我面临的“问题”是我在视图中使用了tryexcept 语句,所以我实际上catch 那些异常(以便在它们被提出时做一些事情) .

我的问题如下:我如何测试一个预期的exception 是否被提出,如果它被我的except 语句捕获?

例如:

myviews.py

class SomeView(LoginRequiredMixin, CreateView):

    model = models.MyModel
    template_name = "my_template.html"
    form_class = forms.MyForm       
    def form_valid(self, form):

        try:
             # normal stuff here
             return super(SomeView, self).form_valid(form)

        except Exception1 as e:
             # some other stuff here
             print("Exception1 occured: ", e)
             messages.error(self.request, "Message1")
             return self.render_to_response(self.get_context_data(form=form))

        except Exception2 as e:
             # some other stuff here
             print("Exception2 occured: ", e)
             messages.error(self.request, "Message2")
             return self.render_to_response(self.get_context_data(form=form))

        except Exception as e:
             # some other stuff here
             print("Something unexpected occured! ", e)
             messages.error(self.request, "Message_unexpected")
             return self.render_to_response(self.get_context_data(form=form))

mytests.py

def test_SomeView(self):

    # test: everything must works just fine
    form_data = some_valid_data
    response = self.client.post("some_url", form_data)
    self.assertEqual(response.status_code, 200)

    # test: Exception1 should be raised in SomeView
    form_data = some_NOT_valid_data # on purpose
    response = self.client.post(reverse("some_url"), form_data)
    for message in list(response.context['messages']): print(message) 
    # UPDATE1 - no message is print, 
    # even if they are displayed as expected on my real web page 
    # when doing willingly bad stuff

非常感谢您的帮助!


更新1

最初,我想这样做:

form_data = some_NOT_valid_data
self.assertRaises(
        Exception1,
        lambda: self.client.post("some_url"), form_data)
    )

但后来我改变了对 jonrsharpe 评论的看法(测试行为多于实现)。因此,当Exceptions 被捕获时,我尝试获取生成的错误消息,这样我就可以检查它们是否符合我的预期。但我显然无法得到任何context message,即使它们在我的模板中按预期显示!然而context不是空的。


UPDATE2 - 回答我自己的问题

我终于找到了管理它的方法。例如,我尝试添加follow=True(如response = self.client.post("some_url", form_data, follow=True),但这是不正确的,因为它不是重定向,而是使用不同的上下文再次呈现相同的视图。所以,我所做的如下:

对于我认为的每个except 声明:

except Exception1 as e:
    # some other stuff here
    print("Exception1 occured: ", e)
    messages.error(self.request, "Message1")
    return self.render_to_response(context=self.get_context_data(form=form, messages=list(messages.get_messages(self.request))))

另外,在我看来,我覆盖了我的 get_context_data 方法:

def get_context_data(self, **kwargs):
    context = super(SomeView, self).get_context_data(**kwargs)
    if 'messages' in kwargs: context['messages'] = kwargs['messages']
    return context

然后,最后,在我的测试中,我能够收到异常消息:

response = self.client.post("some_url", form_data)
self.assertTrue("part_of_message" in str(response.context.get('messages')[0]))

而且它有效!

【问题讨论】:

  • 你无法测试它是否真的被提升了,因为它没有被提升。你抓住了它。这就是您编写的代码的用途。不要测试实现,测试行为;在这种情况下,正确的东西被传递给messages.error
  • 好的,我明白了!现在以这种方式处理听起来合乎逻辑(测试行为多于实现)。抱歉,您必须告诉我,仍在学习正确的方法来进行此类测试。我已经更新了我的问题和我的代码(请在 2 分钟内查看 #UPDATE1),但我仍然无法从上下文中提取任何消息以查看它是否符合我的预期。但是,如果我自己测试它(通过成为我网站的真实用户),则会显示预期的错误消息!所以它必须是我的上下文的一部分......?

标签: python django unit-testing testing exception-handling


【解决方案1】:

我终于成功了(参见我自己的Update 2),并带有@jonrsharpe 的指示。测试行为比绝对测试我一开始想要的更好(如果提出exception,然后被捕获)。所以我努力测试是否正确生成了错误messages,在纠正了我自己的一些错误之后,我终于得到了一些有用的东西!或者没有工作,但正如预期的那样:你明白了。

【讨论】:

    猜你喜欢
    • 2015-11-02
    • 2013-11-30
    • 2014-06-14
    • 2020-11-10
    • 2019-07-06
    • 2018-10-17
    • 2016-01-21
    • 2017-04-15
    • 2011-01-25
    相关资源
    最近更新 更多