如何在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
相关产品推荐
相关产品推荐

