You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在pytest中根据文件名Mock Path实例的is_file方法?

问题:Mock Pathlib的is_file方法,按自定义逻辑返回True/False

我想mock pathlib库的is_file方法,让它根据自定义逻辑返回True或False。

待测试函数在mymodule.py中:

# mymodule.py
from pathlib import Path
def myfun(root: Path):
  return root.is_file()

我写的pytest测试函数遇到了问题:在mock的is_file方法里拿不到当前Path对象的文件名,没法和预设的存在文件列表对比:

import mymodule

# 我的尝试之一
class MockPathIsFile:
    def __init__(self, existing_files):
        self.existing_files = existing_files

    def is_file(self):
        # 此处无法获取文件名(例如"foo.txt"或"nope.txt")以与self.existing_files进行比较。
        if <???> in self.existing_files: 
            return True
        return False

def test_mymodule(monkeypatch):
    monkeypatch.setattr(mymodule.Path, "is_file", MockPathIsFile(existing_files=["foo.txt"]).is_file)
    assert mymodule.myfun(Path("foo.txt")) is True
    assert mymodule.myfun(Path("nope.txt")) is False

这是复杂业务模块的简化示例,实际场景中还需要mock Path.glob和Path.open方法,用来模拟列出文件、读取文件内容的逻辑。


解决方法

方法一:轻量mock单个is_file方法

直接定义一个带self参数的mock函数,利用self访问当前Path实例的文件名(比如self.name或self.as_posix()),这样就能和预设的文件列表对比:

import mymodule
from pathlib import Path

def test_mymodule(monkeypatch):
    existing_files = ["foo.txt"]

    def mock_is_file(self):
        # self就是当前调用is_file的Path实例,取文件名做判断
        return self.name in existing_files

    # 替换mymodule里Path类的is_file方法
    monkeypatch.setattr(mymodule.Path, "is_file", mock_is_file)
    
    assert mymodule.myfun(Path("foo.txt")) is True
    assert mymodule.myfun(Path("nope.txt")) is False

方法二:Mock整个Path类(适合多方法场景)

如果需要同时mockglob、open等多个Path方法,直接自定义一个MockPath类,在类里统一实现所有需要的逻辑,每个方法都能访问到实例存储的路径值:

import mymodule
from io import StringIO

class MockPath:
    def __init__(self, path):
        self.path = path
        # 可以把存在的文件列表作为参数传入,更灵活
        self.existing_files = ["foo.txt", "bar.txt"]

    def is_file(self):
        return self.path in self.existing_files

    # 模拟glob方法:返回匹配模式的文件实例
    def glob(self, pattern):
        # 简单示例:匹配后缀名,实际可根据需求调整逻辑
        suffix = pattern.lstrip("*")
        matched_files = [f for f in self.existing_files if f.endswith(suffix)]
        return [MockPath(f) for f in matched_files]

    # 模拟open方法:返回模拟的文件对象
    def open(self, mode="r"):
        return StringIO(f"模拟读取{self.path}的内容")

def test_mymodule(monkeypatch):
    # 替换mymodule中的Path为自定义的MockPath
    monkeypatch.setattr(mymodule, "Path", MockPath)
    
    assert mymodule.myfun(MockPath("foo.txt")) is True
    assert mymodule.myfun(MockPath("nope.txt")) is False

    # 测试glob方法的示例
    root = MockPath(".")
    assert len(list(root.glob("*.txt"))) == 2

内容的提问来源于stack exchange,提问作者aless80

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 18:25:23