0

我正在尝试测试一个函数,其中一个调用会导致写入多个文件:

def pull_files(output_files=[]):
    for output_file in output_files:
        content = get_content_from_server(output_file)
        with open('/output/' + output_file, "wb") as code:
            code.write(content)

我希望我的测试检查每个调用是否按预期打开,并且内容是否已写入:

def test_case(self):
    pull_files("file1.txt", "file2.txt")

    # Assert open("file1.txt", "wb") was called
    # Assert "file 1 content" was written to "file1.txt"

    # Assert open("file2.txt", "wb") was called
    # Assert "file 2 content" was written to "file2.txt"

我在这里看到了一个处理两个文件的示例:Python mock builtin 'open' in a class using two different files

但是我不知道如何跟踪实际写入他们的内容。

4

2 回答 2

0

这是一个模拟open并返回 aStringIO作为上下文的示例:

from io import StringIO

def my_function(*fns):
    for i, fn in enumerate(fns):
        with open(fn, "wt") as fp:
            fp.write("content %d" % i)


string_io_one = StringIO()
string_io_two = StringIO()
with mock.patch("%s.open" % __name__) as open_mock:
    open_mock.return_value.__enter__.side_effect = [string_io_one, string_io_two]
    my_function("file1.txt", "file2.txt")

    assert open_mock.called_with("file1.txt")
    string_io_one.seek(0)
    assert string_io_one.read() == "content 0"
    assert open_mock.called_with("file2.txt")
    string_io_two.seek(0)
    assert string_io_two.read() == "content 1"

同样,您可以模拟“常规”使用open(没有上下文管理器)。

所做的编辑:更改为涵盖原始问题的测试用例。

于 2020-03-02T15:49:22.830 回答
0

首先,您不应该使用可变对象作为函数的默认参数,这是一种反模式。您应该将您的函数签名更改为def pull_files(output_files=())

然后,对于你的问题,你可以做os.chdir一个/tmp/临时目录,然后在临时文件夹中写入文件。不要忘记将您的工作目录更改回测试后的状态。

另一种解决方案是稍微修改您的函数,以便您不添加前缀 ( '/output/' + output_file)。这样,您可以传递一个io.BytesIO对象而不是路径,这将允许您修改内存中的内容。

于 2020-03-02T15:45:04.487 回答