模拟Popen以根据call_args返回不同的结果

时间:2018-08-02 17:03:33

标签: python python-3.x python-2.7 pytest

我正在调用函数def sftp(cmdstr, server):,该函数调用Popen来调用系统sftp客户端。

我遇到的问题是我有一个main函数,该函数用不同的参数两次调用sftp。第一次使用ls,第二次使用get文件。我嘲笑了电话,但我想不出如何分支返回值。

如果第一个电话我希望它链接到下面以返回一个字符串。 如果第二次调用,我希望它使用tmpdir.mkdir()创建文件,以使文件“出现”,就好像它们已被下载一样。由于代码稍后会进行操作,因此文件必须实际存在。

p_open = mocker.patch('mymodule.Popen', autospec=True)
mock_rv = mocker.Mock()
mock_rv.returncode = None
stdout_sftp = 'sftp> cd /upload\nsftp> ' \
    'ls\n{0}               {1}               \n{2}' \
    '               \nsftp> bye\n'.format(
        sftp_idf_file_list[0],
        sftp_idf_file_list[1],
        sftp_idf_file_list[2]
    )
mock_rv.communicate.return_value = [stdout_sftp, 'output_err']
p_open.return_value = mock_rv

任何人都知道如何制作:    mock_rv.communicate.return_value = [stdout_sftp, 'output_err'] 是指仅在设置期间才调用模拟时才调用的函数?

还有一个警告,代码必须与python2.7和3.6兼容。

此致

瑞安

1 个答案:

答案 0 :(得分:1)

答案是使用lambda和monkeypatch。

首先我们模拟对Popen的调用,以便拥有所有属性,然后设置返回码,以免在主代码中出错。

最后,我们在通讯中设置lambda,这实际上是我们进行sftp调用的地方。如果我的呼叫中包含“ ls”,我想要一个目录列表,以便从sftp呼叫返回一个标准输出的字符串。 另一方面,在这种情况下,如果没有“ ls”,我想运行get命令,因此,不是执行“ getting”,而是执行在目标目录中创建文件的方法。

stdout_sftp = 'sftp> cd /upload\nsftp> ' \
    'ls\n{0}               {1}               \n{2}' \
    '               \nsftp> bye\n'.format(
        sftp_idf_file_list[0],
        sftp_idf_file_list[1],
        sftp_idf_file_list[2]
    )

def create_tmp_files(tdir, flist):
    """ Used to create temp files to simulate sftp"""
    for file_ in flist:
        current_file = tdir.join(file_)
        current_file.write('')
    return "stdout", "stderror"


monkeypatch.setattr('mymodule.Popen', mocker.Mock())
monkeypatch.setattr('mymodule.Popen.return_value.returncode',
                    None)
monkeypatch.setattr('mymodule.Popen.return_value.communicate',
                    lambda x: (stdout_sftp, "stderror")
                    if '\nls\n' in x
                    else create_tmp_files(
                        dst_dir,
                        file_list))