模拟python中的子模块在子模块方法调用中获取错误

时间:2017-03-21 18:46:27

标签: python python-2.7 mocking

我正在尝试在我的应用程序中模拟子进程模块

from subprocess import PIPE
import sys
from mock import MagicMock

from django.test import TestCase


def mockNMCLI(command_list, stdout, stderr):
    return {'communicate': (lambda: ("hello", ""))}


def mockPipe():
    return PIPE


sys.modules['subprocess'] = MagicMock()
sys.modules['subprocess.Popen'] = mockNMCLI
sys.modules['subprocess.PIPE'] = mockPipe


from robot_configuration_interface.helpers import network_manager # NOQA

class NetworkManagerTestCase(TestCase):  
    def test_list_available_networks(self):
       self.assertIsInstance(network_manager.list_connections(), (list))

这是关联函数和从被测试模块的导入。

from subprocess import Popen, PIPE
# ........
def list_connections():
    process = Popen(["nmcli", "-t", "-fields", "NAME,TYPE", "con", "list"], stdout=PIPE, stderr=PIPE)
    stdout, stderr = process.communicate() # <--- Here's the failure
    return stdout

然而,这是失败的:

  

ValueError:在process.communicate()

中解包需要超过0个值

这显然是因为Popen没有被正确嘲笑。但为什么不呢。

1 个答案:

答案 0 :(得分:0)

您未能以多种方式正确使用该软件包:不要通过sys.modules中的直接分配进行修补,因为该修补程序之后不会被撤消并且可能会破坏各种各样的事情。

首先,正确地进行模拟,以便它知道如何解压缩:

>>> mock_popen = MagicMock()
>>> mock_popen.communicate.return_value = 'hello', 'world'
>>> stdout, stderr = mock_popen.communicate()
>>> stdout, stderr
('hello', 'world')

然后使用上下文管理器修补,如下所示:

with mock.patch('path.where.you.import.Popen', mock_popen):
    the_code_that_uses_popen()
mock_popen.assert_called_with(...)