繁体   English   中英

模拟子进程

[英]mocking subprocess.Popen

我有一个模块utils.py具有此run_cmd()方法

def run_cmd(cmd):
    pipe = subprocess.Popen(cmd,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    print(pipe.communicate())
    print(pipe.returncode)
    stdout, stderr = [stream.strip() for stream in pipe.communicate()]
    output = ' - STDOUT: "%s"' % stdout if len(stdout) > 0 else ''
    error = ' - STDERR: "%s"' % stdout if len(stderr) > 0 else ''
    logger.debug("Running [{command}] returns: [{rc}]{output}{error}".format(
                 command=cmd,
                 rc=pipe.returncode,
                 output=output,
                 error=error))

    return pipe.returncode, stdout, stderr

我编写了一个使用模拟的单元测试,并将此链接stackoverflow作为参考

  @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)

为什么pipe.communicate()不打印('output','error')或pipe.returncode不打印0,而是打印模拟方法? 哪里出错了? 我该如何解决?

嗯,您已经有了问题的答案。 仔细观察,您会知道为什么。 您必须像logger一样进行模拟。 您在创建模拟对象时忘了提及utils

@patch('utils.subprocess.Popen')

现在,用多个值模拟嵌套函数,我认为您应该看一下side_effectshere

我尚未测试以下代码,但我希望它应该起作用或至少能给您带来一些帮助。

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

希望对您有所帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM