断言两个文件已正确写入

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

我如何断言该函数在测试中写入了这些文件?

def write() -> None:
    with open('./foo', 'w') as f:
        f.write('fooo')
    with open('./bar', 'w') as f:
        f.write('baar')
class Test:
    @patch('builtins.open', idk)
    def test_write(self, something: MagicMockOrSomething) -> None:
        write()
        something.assert_somehow_foo_contains_fooo()
        something.assert_somehow_bar_contains_baar()

如果可能的话,我想使用带有

@patch
的装饰器语法。

文档仅显示一个文件,并且不使用装饰器:https://docs.python.org/3/library/unittest.mock.html#mock-open

python mocking python-unittest python-unittest.mock
1个回答
0
投票

似乎没有简单的解决方案。

open_mock.mock_calls
(不要这样做
open_mock().mock_calls
,否则你不会收到打开文件的调用)包含对所有文件的操作

您可以在

mock_calls
列表中测试固定索引。类似的东西

class Test:
    @patch("builtins.open", new_callable=mock_open)
    def test_write(self, open_mock: MagicMock) -> None:
        write()

        assert open_mock.mock_calls[0][1] == ('./foo', 'w')
        assert open_mock.mock_calls[2][1] == ('fooo',)

        assert open_mock.mock_calls[4][1] == ('./bar', 'w')
        assert open_mock.mock_calls[6][1] == ('baar',)

或者,如果需要更复杂的东西,您可以使用这个辅助函数,尽管我强烈建议您的测试尽可能简单:

class Test:
    @patch("builtins.open", new_callable=mock_open)
    def test_write(self, open_mock: MagicMock) -> None:
        write()
        self.assert_written_to_file(
            open_mock,
            "./foo",
            "fooo"
        )
        self.assert_written_to_file(
            open_mock,
            "./bar",
            "baar"
        )

    def assert_written_to_file(
        self,
        open_mock: MagicMock,
        path: str,
        payload: str,
        mode: str = "w",
    ) -> None:
        open_mock.assert_any_call(path, mode)

        # There may be multiple calls to open files in the call history.
        # After a call to open a file, it is followed by a call to `__enter__()`, until
        # it is closed with `__exit__()`. Find all calls between enter and exit.
        file_opened = False
        write_calls = []
        for call in open_mock.mock_calls:
            if call[0] == "" and call[1] == (path, mode):
                file_opened = True

            if call[0] == "().write" and file_opened:
                write_calls.append(call)

            if file_opened and call[0] == "().__exit__":
                # Other files may be opened afterward.
                break

        written_payloads = [call[1][0] for call in write_calls]
        if payload not in written_payloads:
            raise AssertionError(
                f'Could not find call to save payload "{payload}" in {written_payloads}'
            )
© www.soinside.com 2019 - 2024. All rights reserved.