模拟函数引发异常以测试except块 [英] Mocking a function to raise an Exception to test an except block

查看:79
本文介绍了模拟函数引发异常以测试except块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数(foo),该函数调用了另一个函数(bar).如果调用bar()会引发一个HttpError,则我想特别处理状态代码为404的情况,否则请重新引发.

I have a function (foo) which calls another function (bar). If invoking bar() raises an HttpError, I want to handle it specially if the status code is 404, otherwise re-raise.

我正在尝试围绕此foo函数编写一些单元测试,以模拟对bar()的调用.不幸的是,我无法对bar()进行模拟调用以引发被我的except块捕获的异常.

I am trying to write some unit tests around this foo function, mocking out the call to bar(). Unfortunately, I am unable to get the mocked call to bar() to raise an Exception which is caught by my except block.

这是说明我问题的代码:

Here is my code which illustrates my problem:

import unittest
import mock
from apiclient.errors import HttpError


class FooTests(unittest.TestCase):
    @mock.patch('my_tests.bar')
    def test_foo_shouldReturnResultOfBar_whenBarSucceeds(self, barMock):
        barMock.return_value = True
        result = foo()
        self.assertTrue(result)  # passes

    @mock.patch('my_tests.bar')
    def test_foo_shouldReturnNone_whenBarRaiseHttpError404(self, barMock):
        barMock.side_effect = HttpError(mock.Mock(return_value={'status': 404}), 'not found')
        result = foo()
        self.assertIsNone(result)  # fails, test raises HttpError

    @mock.patch('my_tests.bar')
    def test_foo_shouldRaiseHttpError_whenBarRaiseHttpErrorNot404(self, barMock):
        barMock.side_effect = HttpError(mock.Mock(return_value={'status': 500}), 'error')
        with self.assertRaises(HttpError):  # passes
            foo()

def foo():
    try:
        result = bar()
        return result
    except HttpError as error:
        if error.resp.status == 404:
            print '404 - %s' % error.message
            return None
        raise

def bar():
    raise NotImplementedError()

我遵循了模拟文档,其中说:您应该将Mock实例的side_effect设置为Exception类,以使模拟函数引发错误.

I followed the Mock docs which say that you should set the side_effect of a Mock instance to an Exception class to have the mocked function raise the error.

我还查看了其他一些相关的StackOverflow Q& A,看来我正在做他们正在做的相同事情,以使他们的模拟引发异常.

I also looked at some other related StackOverflow Q&As, and it looks like I am doing the same thing they are doing to cause and Exception to be raised by their mock.

  • https://stackoverflow.com/a/10310532/346561
  • How to use Python Mock to raise an exception - but with Errno set to a given value

为什么设置barMockside_effect不会导致预期的Exception升高?如果我做的事情很奇怪,应该如何在except块中测试逻辑?

Why is setting the side_effect of barMock not causing the expected Exception to be raised? If I am doing something weird, how should I go about testing logic in my except block?

推荐答案

您的模拟正在引发异常,但是error.resp.status值丢失了.而不是使用return_value,只需告诉Mock status是属性:

Your mock is raising the exception just fine, but the error.resp.status value is missing. Rather than use return_value, just tell Mock that status is an attribute:

barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')

Mock()的其他关键字参数设置为结果对象的属性.

Additional keyword arguments to Mock() are set as attributes on the resulting object.

我将您的foobar定义放在 https://github.com/google/google-api-python-client/blob/master中的my_tests模块中/googleapiclient/errors.py#L35-L63"rel =" noreferrer> HttpError类,这样我也可以使用它,然后您的测试就可以成功运行:

I put your foo and bar definitions in a my_tests module, added in the HttpError class so I could use it too, and your test then can be ran to success:

>>> from my_tests import foo, HttpError
>>> import mock
>>> with mock.patch('my_tests.bar') as barMock:
...     barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
...     result = my_test.foo()
... 
404 - 
>>> result is None
True

您甚至可以看到print '404 - %s' % error.message行,但是我想您想在那里使用error.content;这就是HttpError()从第二个参数开始设置的属​​性,无论如何.

You can even see the print '404 - %s' % error.message line run, but I think you wanted to use error.content there instead; that's the attribute HttpError() sets from the second argument, at any rate.

这篇关于模拟函数引发异常以测试except块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆