Mock/Test 调用 Path.open

Mock/Test Calls to Path.open

我正在尝试为调用 pathlib.Path 上的 open 方法的函数编写单元测试。我能够毫无问题地成功模拟 open 方法,但很难验证该函数是否具有正确的行为。请参阅下面的示例代码:

def test_my_function(self):
    with patch.object(Path, 'open') as mock_open:
        my_function(*args)  # This function calls Path.open

当我反省 mock_open 并查看 _mock_mock_calls 列表时,我无法找到正在写入的文件的字符串路径。通话记录如下所示:

[
    call(mode='w'),
    call().__enter__(),
    call().__enter__().write('<file contents>'),
    call().__enter__().flush(),
    call().__exit__(None, None, None),
]

有没有办法测试调用 Path.open 时打开的路径?

您用模拟对象替换了一个方法。此处使用模拟对象的问题是它 不会绑定到 Path() 实例 。它会被调用,但没有返回 Path() 实例的路径(没有双关语意)。

使用函数模拟 open(),returns 一个 mock_open() object 来跟踪进一步 'open file' 使用,函数 Path:

的实例上访问时被绑定
from unittest.mock import patch, mock_open

def test_my_function(self):
    opener = mock_open()
    def mocked_open(self, *args, **kwargs):
        return opener(self, *args, **kwargs)
    with patch.object(Path, 'open', mocked_open):
        my_function(*args)  # This function calls Path.open

现在任何 Path().open() 调用都将调用 opener 模拟,记录所有文件交互 调用它的 Path() 对象:

>>> from pathlib import Path
>>> from unittest.mock import patch, mock_open
>>> opener = mock_open()
>>> def mocked_open(self, *args, **kwargs):
...     return opener(self, *args, **kwargs)
...
>>> with patch.object(Path, 'open', mocked_open):
...     print(Path.open)
...     print(Path().open)
...     with Path().open() as f:
...         f.write('<file contents>')
...         f.flush()
...
<function mocked_open at 0x12026f5c0>
<bound method mocked_open of PosixPath('.')>
<MagicMock name='open().flush()' id='4834728928'>
>>> opener.mock_calls
[call(PosixPath('.')),
 call().__enter__(),
 call().write('<file contents>'),
 call().flush(),
 call().__exit__(None, None, None)]