或:如何模拟未直接调用的方法?
在这种情况下方法 baz
我正在使用pypi的Mock package
### tests
# ...
def test_method_a(self):
# how to mock method that is called from bar() ?
obj = foo.bar()
self.assertEqual(obj.get('x'), 12345)
### foo
# ...
def bar():
x = some_module.baz() # <- how to mock baz() ?
return x
答案 0 :(得分:3)
以下示例应该向您展示它的工作原理:
from mock import patch
def baz():
return 'y'
def bar():
x = baz() # <- how to mock baz() ?
return x
def test():
with patch('__main__.baz') as baz_mock:
baz_mock.return_value = 'blah'
assert bar() == 'blah'
test()
答案 1 :(得分:0)
恕我直言这个例子更好地说明了单元测试中的常见用例。
重要的部分是@patch
装饰器,它有效地替换了正在修补的函数的side_effect
函数(这也可能只是一个值)。棘手的位通常是获得修补功能的完整包路径。请注意您必须使用'__main__.func'
来引用修补函数。
第一个测试test_func
检查测试的模拟值是原始预期函数值('Hello World!'
)。第二个测试test_mocked_func
补丁func
实际上是函数对象new_func
,因此返回True
。第三个测试说明将值替换为side_effect
而不是新函数。事实上,由于我们使替换值成为可迭代的(side_effect=['New String 1!', 'New String 2!', 3]
),因此每次运行时,它都会返回一个新值。
警告:如果您尝试调用修补函数的时间超过指定的返回值(本例中为3),则会出现StopIteration
错误,因为您没有定义足够的返回side_effect
中的值。
import unittest
from mock import patch # for Python 2.7
# from unittest.mock import patch # for Python 3.5
def func():
return 'Hello World!'
def newFunc():
return True
class TestFunc(unittest.TestCase):
def test_func(self):
self.assertEqual(func(), 'Hello World!')
@patch('__main__.func', side_effect=newFunc)
def test_mocked_func(self, *patches):
self.assertTrue(func())
@patch('__main__.func', side_effect=['New String 1!', 'New String 2!', 3])
def test_mocked_func_again(self, *patches):
self.assertEqual(func(), 'New String 1!')
self.assertEqual(func(), 'New String 2!')
self.assertEqual(func(), 3)
# func() # This breaks the test because we only specified a list of length 3 in our patch.
if __name__=='__main__':
unittest.main()