Mocking open () для pathlib.Path для возврата дескриптора ложного файла с помощью unittest.mock - PullRequest
1 голос
/ 28 февраля 2020

Скажем, у меня есть метод, который пропускает некоторые пути, читает файлы по каждому из этих путей, затем возвращает словарь из имени файла в содержимое файла, например:

from contextlib import ExitStack
from pathlib import Path


class ClassToTest:
    def method_to_test(self, *paths: Path):
        with ExitStack() as stack:
            files = [stack.enter_context(path.open(mode='r')) for path in paths]
            return {f.name: f.read() for f in files}

Теперь скажите, что я хочу чтобы проверить, что если я передам, например, C:\wherever\file_name.xyz, то возвращаемый словарь содержит ключ file_name.xyz. Поскольку мой тестируемый метод - открытие и чтение файлов, я хочу смоделировать объект Path. Я думаю, что могу сделать что-то вроде :

from unittest.mock import Mock, mock_open

class Tests:
    def test(self):
        mock_path = Mock(spec=Path)
        mock_path.open = mock_open()
        # ???

        files = ClassToTest().method_to_test(mock_path)
        assert 'file_name.xyz' in files

Но я не могу понять, как заставить f.name (то есть mock_path.open().name) вернуть file_name.xyz.

1 Ответ

0 голосов
/ 28 февраля 2020

Попробуйте assert mock_path.open().name in files. Должно просто работать, как вы используете библиотеку насмешек. Это будет тест fr agile, хотя mock_path.name != mock_path.open().name

. Если вы используете pytest, просто используйте прибор tmp_path, который уникален для каждого вызова теста.

import pytest

def f(path):
    with path.open() as f:
        return {f.name: f.read()}

def test_f(tmp_path):
    name = 'some_file.txt'
    content = 'hello\nworld'
    path = tmp_path / name
    path.write_text(content)

    result = f(path)

    assert str(path) in result
    assert content in result.values()

def test_g(tmp_path):
    assert list(tmp_path.iterdir()) == []
...