Python 模拟一个函数来引发一个异常来测试一个except块
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28305406/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mocking a function to raise an Exception to test an except block
提问by Jesse Webb
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()引发了一个HttpError,如果状态码为 404,我想特别处理它,否则重新引发。
I am trying to write some unit tests around this foofunction, 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 exceptblock.
我正在尝试围绕此foo函数编写一些单元测试,模拟对bar(). 不幸的是,我无法获得模拟调用bar()以引发由我的except块捕获的异常。
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()
I followed the Mock docswhich say that you should set the side_effectof a Mockinstance to an Exceptionclass to have the mocked function raise the error.
我跟着模拟文档这不能不说您应该设置side_effect一个的Mock情况下,以一个Exception班有嘲笑功能引发错误。
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.
我还查看了其他一些相关的 StackOverflow 问答,看起来我正在做同样的事情,他们正在做的事情是导致他们的模拟引发异常。
- https://stackoverflow.com/a/10310532/346561
- How to use Python Mock to raise an exception - but with Errno set to a given value
Why is setting the side_effectof barMocknot causing the expected Exceptionto be raised? If I am doing something weird, how should I go about testing logic in my exceptblock?
为什么设置side_effect的barMock不引起预期Exception得到提升?如果我做了一些奇怪的事情,我应该如何在我的except块中测试逻辑?
采纳答案by Martijn Pieters
Your mock is raising the exception just fine, but the error.resp.statusvalue is missing. Rather than use return_value, just tell Mockthat statusis an attribute:
您的模拟很好地引发了异常,但error.resp.status缺少该值。而不是 use return_value,只需告诉Mock它status是一个属性:
barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
Additional keyword arguments to Mock()are set as attributes on the resulting object.
附加的关键字参数Mock()设置为结果对象的属性。
I put your fooand bardefinitions in a my_testsmodule, added in the HttpErrorclassso I could use it too, and your test then can be ran to success:
我将您的foo和bar定义放在一个my_tests模块中,添加到HttpError类中,以便我也可以使用它,然后您的测试可以成功运行:
>>> 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
You can even see the print '404 - %s' % error.messageline run, but I think you wanted to use error.contentthere instead; that's the attribute HttpError()sets from the second argument, at any rate.
您甚至可以看到print '404 - %s' % error.message线路运行,但我认为您想在error.content那里使用;HttpError()无论如何,这是第二个参数的属性集。

