我有一个程序需要根据某些逻辑编写具有不同内容的不同文件。
我尝试编写一个
assert_file_written_with_content(filepath: str, content: str)
函数来访问mock_open并检查内容是否已尝试写入该文件路径。
这是我的尝试
@pytest.fixture(autouse=True)
def mock_open_file(self, mocker):
mocker.patch("builtins.open", mock_open(), create=True)
def assert_file_written_with_content(file_path, content):
"""When file is opened using builtins.open and this is mocked in the test, assert that the file is written with the given content."""
mock_open_file = builtins.open
for call in mock_open_file.call_args_list:
if call.args[0] == file_path and call.args[1] == "w":
call.return_value.write.assert_called_with(content)
return
raise AssertionError(f"File {file_path} was not written with content {content}")
由于某种原因,它总是在过去;即使内容不匹配。
为什么内容错误时没有出现断言错误?
如果在运行 pytest 时出现不匹配,您可以让测试打印文件路径和内容中的比较,那就加分了。
我现在有了这个,看起来可行,但也很老套,我觉得一定有更好的方法:
import builtins
from testfixtures import compare
def assert_file_written_with_content(file_path, content):
"""When file is opened using builtins.open and this is mocked in the test, assert that the file is written with the given content."""
mock_open_file = builtins.open
for i, call in enumerate(mock_open_file.mock_calls[::4]):
current_iteration = i * 4
if call.args[0] == file_path and call.args[1] == "w":
call_write = mock_open_file.mock_calls[current_iteration + 2]
compare(content, call_write[1][0])
return
raise AssertionError(f"File {file_path} was not written with content {content}")
我对你的代码有点困惑;在第二个示例中,您似乎没有模拟
open
方法,而在第一个示例中,您有一个 mock_open_file
固定装置,但您似乎没有使用它。
以下示例演示了在调用
write
方法时断言的一种方法;有通过的测试和失败的测试来证明它按预期工作:
from unittest import mock
def func_that_writes_a_file():
with open('myfile.txt', 'w') as fd:
fd.write('hello world\n')
def test_open_succeeds():
mock_open = mock.mock_open()
with mock.patch('builtins.open', mock_open):
func_that_writes_a_file()
assert mock_open.return_value.write.call_args[0][0] == 'hello world\n'
def test_open_fails():
mock_open = mock.mock_open()
with mock.patch('builtins.open', mock_open):
func_that_writes_a_file()
assert mock_open.return_value.write.call_args[0][0] == 'goodbye world\n'
也可以对文件内容进行断言,而不是对
write
的调用;如果您正在测试的内容是由多个 write
调用创建的,这非常有用。在此版本的代码中,我们创建一个 io.StringIO()
对象并将其用作 open
的返回值,以便我们可以使用 getvalue()
方法测试内容:
import io
import pytest
from unittest import mock
def func_that_writes_a_file():
with open("myfile.txt", "w") as fd:
fd.write("hello world\n")
@pytest.fixture
def mock_open():
buffer = io.StringIO()
# We need to disable the `close` method, since we can't call
# getvalue() on a closed StringIO object.
buffer.close = lambda: None
mock_open = mock.mock_open()
mock_open.return_value = buffer
return mock_open
def test_open_succeeds(mock_open):
with mock.patch("builtins.open", mock_open):
func_that_writes_a_file()
assert mock_open.return_value.getvalue() == "hello world\n"
def test_open_fails(mock_open):
with mock.patch("builtins.open", mock_open):
func_that_writes_a_file()
assert mock_open.return_value.getvalue() == "goodbye world\n"