Python mocking subprocess.Popen

Python mocking subprocess.Popen,python,python-2.7,mocking,subprocess,Python,Python 2.7,Mocking,Subprocess,我有一个模块utils.py,它有这个run\u cmd()方法 我使用mock和这个链接作为参考编写了一个单元测试 @patch('subprocess.Popen') @patch('utils.logger.debug') def test_run_cmd(self, mock_popen, mock_log): cmd = 'mock_command' mocked_pipe = Mock() attrs = {'communicate.return_

我有一个模块utils.py,它有这个run\u cmd()方法

我使用mock和这个链接作为参考编写了一个单元测试

  @patch('subprocess.Popen')
  @patch('utils.logger.debug')
  def test_run_cmd(self, mock_popen, mock_log):
    cmd = 'mock_command'
    mocked_pipe = Mock()
    attrs = {'communicate.return_value': ('output', 'error'), 'returncode': 0}
    mocked_pipe.configure_mock(**attrs)
    mock_popen.return_value = mocked_pipe
    log_calls = [call('Running [mock_command] returns: [0]outputerror')]
    utils.run_cmd(cmd)
    mock_popen.assert_called_once_with(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    mock_log.assert_has_calls(log_calls)
当我运行鼻测试时,我得到了这个作为输出

        stdout, stderr = [stream.strip() for stream in pipe.communicate()]
ValueError: need more than 0 values to unpack
-------------------- >> begin captured stdout << ---------------------
<MagicMock name='Popen().communicate()' id='140197276165008'>
<MagicMock name='Popen().returncode' id='140197276242512'>

--------------------- >> end captured stdout << ----------------------
FAILED (errors=1)
stdout,stderr=[stream.strip()用于管道中的流。communicate()]
ValueError:需要0个以上的值才能解包

-------------------->>开始捕获stdout>结束捕获stdout啊,你的问题已经有答案了。仔细看,你就会知道原因。您必须像对待
记录器那样进行模拟。在创建模拟对象时,您忘记提到了
utils

@patch('utils.subprocess.Popen')
现在,用多个值模拟嵌套函数,我认为您应该看看and

我还没有测试下面的代码,但我希望它能起作用,或者至少能给你一些线索

mocked_open.return_value.communicate.return_value = ('output', 'error')
mocked_open.return_value.returncode = 0

希望这会有帮助

我可以用这种方式模仿管道
@patch('utils.subprocess.Popen.communicate',return_value=('output',error'))
如何模拟管道。returncode?更新答案以使用
副作用
和其他hi,感谢您的建议。我终于解决了。但是我修补了subprocess而不是subprocess.Popen
mock_subprocess.Popen.return_value.communicate.return_value=('output','error')
mock_subprocess.Popen.return_value.returncode=0
。你成功了!
mocked_open.return_value.communicate.return_value = ('output', 'error')
mocked_open.return_value.returncode = 0