我有一个调用另一个函数(foo
)的函数(bar
)。如果调用bar()
引发HttpError
,我想特别处理它,如果状态代码是404,否则重新加注。
我正在尝试围绕此foo
函数编写一些单元测试,模拟对bar()
的调用。不幸的是,我无法通过模拟调用bar()
来引发由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 docs说明您应该将side_effect
实例的Mock
设置为Exception
类,以使模拟函数引发错误。
我还看了一些其他相关的StackOverflow Q& As,看起来我正在做他们正在做的同样的事情,并且他们的模拟引发了异常。
为什么设置side_effect
的{{1}}不会导致预期barMock
被提升?如果我做了一些奇怪的事情,我应该如何在Exception
块中测试逻辑?
答案 0 :(得分:94)
你的模拟正在提升异常,但error.resp.status
值丢失了。不要使用return_value
,只需告诉Mock
status
是一个属性:
barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
Mock()
的其他关键字参数在结果对象上设置为属性。
我将foo
和bar
定义放在my_tests
模块中,添加到HttpError
class中,因此我也可以使用它,然后您的测试可以运行到成功:
>>> 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()
。