使用pyfakefs在类变量中伪造pathlib.Path

1 投票
1 回答
39 浏览
提问于 2025-04-14 18:11

我有一个类变量,它的类型是 pathlib.Path

from pathlib import Path


class MyClass:
    FILE_PATH = Path('/etc/ids.json')

我知道 pyfakefs 不能自动模拟这个东西。所以在我的测试中,我使用它的 Patcher 类(我也试过其他方法)来重新加载对应的模块。

from pathlib import Path
from pyfakefs.fake_filesystem_unittest import Patcher
from pyfakefs.fake_pathlib import FakePathlibModule

from . import my_class


def test_class_variable(fs):
    # my_class.MyClass.FILE_PATH = Path('/etc/ids.json')
    with Patcher(modules_to_reload=[my_class]):
        assert type(my_class.MyClass.FILE_PATH) is FakePathlibModule.PosixPath

但是它还是没有被模拟。

如果我取消注释那行被注释掉的代码,测试就成功了。

我该怎么做才能模拟这个类变量呢?

1 个回答

3

这里的问题是你创建了两个补丁器:一次是通过 fs 这个工具创建的,另一次是手动通过 Patcher 来实例化的。

pyfakefs 不支持嵌套的文件系统模拟——如果你尝试嵌套,它只会使用已经存在的那个。这一点在关于模块和会话范围的工具的警告中有提到,具体可以查看这里,但可能需要在文档中更显眼的位置说明,因为这与使用模块或会话范围的工具无关。

解决这个问题最简单的方法就是直接不使用 fs 这个工具:

def test_class_variable():
    with Patcher(modules_to_reload=[my_class]):
        assert type(my_class.MyClass.FILE_PATH) is FakePathlibModule.PosixPath

如果你需要多次使用这个功能(或者不想在测试中进行这样的设置),你可以创建你自己的工具:

@pytest.fixture
def my_fs():
    with Patcher(modules_to_reload=[my_class]) as p:
        yield p.fs


def test_class_variable(my_fs):
    assert type(my_class.MyClass.FILE_PATH) is FakePathlibModule.PosixPath

免责声明:
我是 pyfakefs 的维护者。

更新:
我在故障排除指南中添加了关于嵌套虚假文件系统的章节

撰写回答