我如何断言该函数在测试中写入了这些文件?
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
似乎没有简单的解决方案。
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}'
)