我有一个带有字典作为关联数组的模块来实现一种切换语句。
def my_method1():
return "method 1"
def my_method2():
return "method 2"
map_func = {
'0': my_method1,
'1': my_method2
}
def disptach(arg):
return map_func[arg]()
如何在测试中模拟my_method1?我尝试了以下但没有成功:
import my_module as app
@patch('my_module.my_method1')
def test_mocking_sample(self, my_mock):
my_mock.return_value = 'mocked'
assert_equal('mocked',app.dispatch('0'))
有什么想法吗?
答案 0 :(得分:1)
这篇patch文档说明如下:
补丁通过(暂时)更改名称所指向的对象来工作 与另一个。可以有许多指向任何个人的名字 对象,所以要修补工作,你必须确保你修补 被测系统使用的名称。
基本上,您的调度员无法看到它,因为在应用补丁之前,映射是为了引用原始方法而构建的。
你可以做的最简单的事情是将映射折叠到dispatch
函数中:
def dispatch(arg):
return {
'0': my_method1,
'1': my_method2
}[arg]()
这确实有缺点,每次调用它时都会重建映射,因此速度会慢一些。
试图变得有点聪明,似乎Python允许你换掉函数的实际代码,如下所示:
>>> f = lambda: "foo"
>>> a = f
>>> g = lambda: "bar"
>>> f.func_code = g.func_code
>>> a()
'bar'
我不推荐你这样做,但也许你可以找到一个支持类似东西的模拟框架。
答案 1 :(得分:1)
正如您所发现的那样,修补my_Method1()
不起作用。这是因为在导入my_module时定义了map_func['0']
,并且对my_Method1()
的后续更改未针对您的测试更新map_func
。相反,我们需要直接修补密钥map_func
的字典'0'
中的值。 unittest.mock documentation解释了如何修补字典条目。以下是您的测试的有效实施:
""" test_my_module.py
"""
import unittest
import unittest.mock as mock
import my_module as app
my_mock = mock.MagicMock()
class Test_mock_sample(unittest.TestCase):
@mock.patch.dict('my_module.map_func', {'0': my_mock})
def test_mocking_sample(self):
my_mock.return_value = 'mocked'
self.assertEqual('mocked', app.dispatch('0'))
if __name__ == '__main__':
unittest.main()
将原始my_module中的disptach
更改为dispatch
...
""" my_module.py
"""
def my_method1():
return "method 1"
def my_method2():
return "method 2"
map_func = {
'0': my_method1,
'1': my_method2
}
def dispatch(arg):
return map_func[arg]()
然后命令python -m unittest test_my_module
给出以下输出:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
有效!