如何模拟不在测试范围内的方法?
如何模拟一个不在测试范围内的方法?
或者:如何模拟一个没有被直接调用的方法?
在这个例子中,我们要模拟的方法是baz
我正在使用来自pypi的Mock包
### 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
2 个回答
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()
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()