Python mock.patch没有修补正确的导入

时间:2013-12-22 16:55:52

标签: python mocking flask patch twill

代码

def test_get_network_info(self):
    with open(dirname(abspath(__file__)) + '/files/fake_network_info.txt', 'r') as mock_network_info:
        with patch('subprocess.check_output', Mock(return_value=mock_network_info.read())):
            self.assertEqual('192.168.1.100', get_network_info()[0])
            self.assertEqual('255.255.255.0', get_network_info()[1])
            self.assertEqual('192.168.1.0', get_network_info()[2])

错误

======================================================================
ERROR: test_get_network_info (tests.test_tools.ToolsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/Documents/overseer/app/tests/test_tools.py", line 21, in test_get_network_info
    with patch('subprocess.check_output', Mock(return_value=mock_network_info.read())):
  File "/usr/local/lib/python2.7/dist-packages/mock.py", line 1268, in __enter__
    original, local = self.get_original()
  File "/usr/local/lib/python2.7/dist-packages/mock.py", line 1242, in get_original
    "%s does not have the attribute %r" % (target, name)
AttributeError: <module 'subprocess' from '/usr/local/lib/python2.7/dist-packages/twill/other_packages/subprocess.pyc'> does not have the attribute 'check_output'

我的理解

我对这个问题的理解是mock试图模仿twillsubprocess模块而不是python模块。

问题

  1. 我做错了吗?

  2. 如何指定我要修补python subprocess模块而不是斜纹的模块? (可能是在测试套件的早期导入的)**

  3. 是否有其他方法可以修补subprocess模块?

  4. 我尝试了什么

    • 我试过with patch('tools.subprocess.check_output', ...

    不起作用。

    • 我厌倦了使用装饰......

    不起作用

    • 我厌倦了直接修补subprocess模块subprocess.check_output = Mock( ...

    工作但不好,因为它不会撤消修补。

    更多信息

    如果我只运行此测试而没有其他测试,那么它的工作原理是因为twill的子进程模块从未被导入过。但是一旦我用斜纹测试进行测试,上面的测试就会失败。

    Here是twill的子流程版本,它看起来像是从旧版本的python中复制粘贴的。它没有任何check_output函数,这就是测试失败的原因。

    Twill的软件包来自我广泛使用的Flask-Testing插件。我在github here上提交了一个问题。

    我希望来自可爱的python社区的人可以提供帮助。 :)

1 个答案:

答案 0 :(得分:1)

在那里看到我的评论,由于斜纹的不良做法,正确的方法是修复斜纹,这可能需要一些工作,或转移到其他东西,但因为你现在严重依赖于烧瓶测试,这也不是一个便宜的举动。

所以这给我们留下了一个肮脏的伎俩:在导入斜纹之前确保import subprocess。在内部,这将在subprocess中添加对sys.modules模块的引用。加载模块后,所有子结果import将不再显示在sys.path中,而只是使用已在sys.modules中缓存的引用。

不幸的是,这可能不是问题的结束。显然twill使用修补版的子进程出于某种原因;并且这些补丁对他不可用,因为将加载普通的内置子进程。它很可能会以意想不到的方式崩溃或表现。如果是这样的话,那么......回到上面的建议。