[英]How to mock using patch relative paths?
我在python测试文件中有这样的东西:
from mock import patch,
from ..monkey import ook
[...]
@patch('monkey.ook', Mock(return_value=None))
def test_run_ook (self, mock_ook):
self.assertIsNone(ook())
mock_ook.run.assert_called_once_with('')
当我运行此测试时,我得到一个ImportError: No module named monkey
。 显然,我修补的道路是不对的。 但是,我不确定如何在不弄乱sys.path
或PYTHONPATH
情况下做到正确。
有什么指针吗?
从我收集到的,使用mock,你需要在修补时提供虚线名称。 幸运的是,每个模块都可以访问包含模块名称的特殊模块级变量__name__
。 使用此方法,如果要修改模块本地的变量,您应该可以执行以下操作:
import mock
import unittest
ook = lambda: "the ook"
class OokTest(unittest.TestCase):
def test_ook(self):
with mock.patch(__name__ + '.ook', return_value=None):
self.assertIsNone(ook())
self.assertEquals(ook(), "the ook")
# the patch decorator should work the same way, I just tend to use the
# context manager out of personal preference
@mock.patch(__name__ + '.ook', return_value=None)
def test_ook_2(self, mock_ook):
self.assertIsNone(ook())
假设您已将该文件保存为quicktest.py
,则单元测试会给出以下结果:
$ python -m unittest quicktest
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
当然, from ab import c
到你的包中给你一个简单的变量c
,所以这个机制应该有效。
我使用了Dan Passaro的解决方案,直到我使用patch.object
遇到了这个解决方案 - 这看起来对我来说更好:
from unittest.mock import patch,
from .. import monkey
[...]
@patch.object(monkey, 'ook', Mock(return_value=None))
def test_run_ook (self, mock_ook):
self.assertIsNone(monkey.ook())
mock_ook.run.assert_called_once_with('')
好处:
__name__ + '.object_to_be_mocked'
的样板代码 import
语句。 @patch.object(amazon.jungle.monkey, 'ook', …)
,你的IDE的静态代码分析可以确保至少amazon.jungle.monkey
是一个有效的变量,因为你没有把整个东西写成字符串'amazon.jungle.monkey.ook'
。 缺点:
from ..monkey import ook
但是需要做from .. import monkey
并通过monkey
访问ook
,即monkey.ook
。 如果我需要经常写这个,我会在测试开始时添加ook = monkey.ook
以方便起见。 (或者甚至是导入语句,以防我永远不需要模仿monkey
这个特殊属性。) 基于公认的答案,我相信这是实现预期目标的最简洁方法:
from mock import patch
from .. import monkey
@patch(monkey.__name__+'.ook', Mock(return_value=None))
def test_run_ook (self, mock_ook):
self.assertIsNone(monkey.ook())
mock_ook.run.assert_called_once_with('')
不确定这是否是最好的方式(甚至推荐),但一种方法是使用类似的东西:
from mock import patch,
from ..monkey import ook
[...]
package_base = __package__.rsplit('.', 1)[0]
@patch('{0}.monkey.ook'.format(package_base), Mock(return_value=None))
def test_run_ook (self, mock_ook):
self.assertIsNone(ook())
mock_ook.run.assert_called_once_with('')
当你from ..monkey import ook
从模块pkg1.pgk2.mymodule
是你最终什么pkg1.pgk2.mymodule.ook
。
现在, ook
位于执行from ... import ...
的模块的命名空间中。 这就是你需要修补的目标。
所以你只需要修补pkg1.pkg2.mymodule.ook
:
from unittest.mock import patch # mypackage.mymodule.patch
from ..monkey import ook # mypacket.mymodule.ook
with patch("pkg1.pgk2.mymodule.ook"):
....
正如其他人所指出的那样,如果你从导入的同一个模块进行修补,那么你可以使用__name__
来获取虚线包名,但是如果要从另一个模块进行修补,则需要拼写出来。
请记住,您导入的任何内容都可以从目标modulethatimports.nameimported
。
我认为这是因为你不进口monkey
而是导入ook
。 如果您从..
导入猴子,那么它应该工作。 否则,只需在ook
上调用patch。
使用导入的完整路径。 例如,如果您有此文件系统:
您可以使用以下方法从module2.py导入module.py:
from root.dummy.foo import module
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.