我需要模拟pathlib.Path.open
使用pytest-mock
.
真正的open_func
打开一个yaml-file
。返回值是一个常规的dict
。我怎样才能模拟Path.open
只加载另一个yaml-file
被调用的test-config.yaml
?
我的代码无法正常工作,因为conf
它将简单地变成str
(“test_config.yaml”)。它应该是一个dict
.
from pathlib import Path
import yaml
def open_func():
with Path.open(Path("./config.yaml")) as f:
return yaml.load(f, Loader=yaml.FullLoader)
def test_open_func(mocker):
mocker.patch("pathlib.Path.open", mocker.mock_open(read_data="test_config.yaml"))
conf = open_func()
assert isinstance(conf, dict)
编辑:为了更接近我的现实世界问题,我提供了以下代码。我有一个类TryToMock
,它基本上需要两个文件作为输入。该方法load_files
只是加载这些文件(实际上是 .yaml 文件)并返回输出。这些 .yaml 文件实际上是一些配置文件。
在我的单元测试中,我会TryToMock
通过 pytest 的parametrize
. 因此,我想通过fixture
. 然后我可以monkeypatch
在运行之前在我的各种测试中输入一些条目load_files
。
为了不再加载原始文件,我需要Path.open
在TryToMock
. 我想改为传递monkeypatched
yaml 文件(即以 a 的形式dict
)。困难在于我必须区分这两个文件。那就是我不能简单地模拟Path.open
具有相同文件内容的函数。
# TryToMock.py
from pathlib import Path
import yaml
# In my current working folder, I have to .yaml files containing the following
# content for illustrative purpose:
#
# file1.yaml = {'name': 'test1', 'file_type': 'yaml'}
# file2.yaml = {'schema': 'test2', 'currencies': ['EUR', 'USD', 'JPY']}
class TryToMock:
def __init__(self, file_to_mock_1, file_to_mock_2):
self._file_to_mock_1 = file_to_mock_1
self._file_to_mock_2 = file_to_mock_2
def load_files(self):
with Path.open(self._file_to_mock_1) as f:
file1 = yaml.load(f, Loader=yaml.FullLoader)
with Path.open(self._file_to_mock_2) as f:
file2 = yaml.load(f, Loader=yaml.FullLoader)
return file1, file2
# test_TryToMock.py
import os
from pathlib import Path
import pytest
import yaml
from tests import TryToMock
def yaml_files_for_test(yaml_content):
names = {"file1.yaml": file1_content, "file2.yaml": file2_content}
return os.path.join("./", names[os.path.basename(yaml_content)])
@pytest.fixture(scope="module")
def file1_content():
with Path.open(Path("./file1.yaml")) as f:
return yaml.load(f, Loader=yaml.FullLoader)
@pytest.fixture(scope="module")
def file2_content():
with Path.open(Path("./file2.yaml")) as f:
return yaml.load(f, Loader=yaml.FullLoader)
def test_try_to_mock(file1_content, file2_content, monkeypatch, mocker):
file_1 = Path("./file1.yaml")
file_2 = Path("./file2.yaml")
m = TryToMock.TryToMock(file_to_mock_1=file_1, file_to_mock_2=file_2)
# Change some items
monkeypatch.setitem(file1_content, "file_type", "json")
# Mocking - How does it work when I would like to use mock_open???
# How should the lambda function look like?
mocker.patch(
"pathlib.Path.open",
lambda x: mocker.mock_open(read_data=yaml_files_for_test(x)),
)
files = m.load_files()
assert files[0]["file_type"] == "json"