Пробные / тестовые вызовы Path.open - PullRequest
5 голосов
/ 14 марта 2019

Я пытаюсь написать модульный тест для функции, которая вызывает метод open для pathlib.Path.Я могу успешно смоделировать метод 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?

1 Ответ

3 голосов
/ 14 марта 2019

Вы заменили метод на фиктивный объект.Проблема с использованием фиктивного объекта в том, что он не будет привязан к Path() экземпляру .Он будет вызван, но нет пути назад к экземпляру Path() (без каламбура).

Используйте функцию для макета open(), которая возвращает mock_open()объект для отслеживания дальнейшего использования «открытого файла», функции будут связаны при обращении к экземплярам 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)]
...