[英]How do I mock out file writing to multiple files in python
I'm trying to test a function in which one call results in multiple files being written:我正在尝试测试一个函数,其中一次调用会导致写入多个文件:
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)
I want my test to check that each call was made to open as expected, and that the content was written:我希望我的测试检查每个调用是否按预期打开,以及内容是否已写入:
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"
I've seen an example of handling two files here: Python mock builtin 'open' in a class using two different files我在这里看到了一个处理两个文件的例子: Python mock builtin 'open' in a class using two different files
But I can't wrap my head around how to track what is actually written to them.但是我无法理解如何跟踪实际写入它们的内容。
First, you should never use a mutable object as your default argument to a function, which is an anti-pattern .首先,永远不要使用可变对象作为函数的默认参数,这是一个反模式。 You should change your function signature to
def pull_files(output_files=())
instead.您应该将函数签名更改为
def pull_files(output_files=())
。
Then, to your question, you can do a os.chdir
to /tmp/
and make a temporary directory, then write files in the temporary folder instead.然后,对于您的问题,您可以对
/tmp/
执行os.chdir
并创建一个临时目录,然后将文件写入临时文件夹中。 Don't forget to change your working directory back to what it was after the test.不要忘记将您的工作目录改回测试后的状态。
Another solution is to modify your function slightly so that you are not prepending a prefix ( '/output/' + output_file
).另一种解决方案是稍微修改你的函数,这样你就不会在前面加上前缀(
'/output/' + output_file
)。 This way, you can pass an io.BytesIO
object instead of a path, which will let you modify the contents in-memory.这样,您可以传递一个
io.BytesIO
对象而不是路径,这将允许您修改内存中的内容。
Here's an example mocking open
and returning a StringIO
as context:这是一个
StringIO
open
并返回StringIO
作为上下文的示例:
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"
Similarly you could mock out "regular" use of open
(without a context manager).同样,您可以模拟
open
“常规”使用(没有上下文管理器)。
Edits made: Changed to cover the test cases of the original question.所做的编辑:更改以涵盖原始问题的测试用例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.