如何在mock_open上断言以检查特定文件路径是否已在python中写入特定内容?

问题描述 投票:0回答:1

我有一个程序需要根据某些逻辑编写具有不同内容的不同文件。

我尝试编写一个

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}")
python python-unittest.mock
1个回答
0
投票

我对你的代码有点困惑;在第二个示例中,您似乎没有模拟

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"
© www.soinside.com 2019 - 2024. All rights reserved.