嘲笑一个函数来引发Exception来testing一个except块
我有一个函数( foo
)调用另一个函数( bar
)。 如果调用bar()
会引发一个HttpError
,如果状态码是404,我想特别处理,否则重新提升。
我试图围绕这个foo
函数写一些unit testing,嘲笑bar()
的调用。 不幸的是,我无法得到bar()
的模拟电话来提出一个exception,这个exception被我的except
块拦截。
这是我的代码,说明了我的问题:
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文档说,你应该把一个Mock
实例的side_effect
设置成一个Exception
类来让Mock
函数产生错误。
我也看了一些其他相关的StackOverflow问答,看起来我正在做同样的事情,他们正在做的事情和exception由他们的模拟。
- https://stackoverflow.com/a/10310532/346561
- 如何使用Python Mock来引发exception – 但Errno设置为给定的值
为什么设置side_effect
的barMock
不会导致预期的Exception
被提出? 如果我做了一些奇怪的事情,那么我应该如何去testingexcept
块except
逻辑呢?
你的模拟引发exception就好了,但是error.resp.status
值却丢失了。 不要使用return_value
,只要告诉Mock
status
是一个属性:
barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
Mock()
附加关键字参数在结果对象上被设置为属性。
我把你的foo
和bar
定义放在my_tests
模块中,添加到HTTPError
类中,这样我也可以使用它,然后你的testing可以运行成功:
>>> 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()
从第二个参数中设置的属性,无论如何。