有时候,测试用例需要调用某些依赖于全局配置的功能,或者这些功能本身又调用了某些不容易测试的代码(例如:网络接入)。fixture monkeypatch
可以帮助你安全的设置/删除一个属性、字典项或者环境变量,甚至改变导入模块时的sys.path
路径。
monkeypatch
提供了以下方法:
monkeypatch.setattr(obj, name, value, raising=True)
monkeypatch.delattr(obj, name, raising=True)
monkeypatch.setitem(mapping, name, value)
monkeypatch.delitem(obj, name, raising=True)
monkeypatch.setenv(name, value, prepend=False)
monkeypatch.delenv(name, raising=True)
monkeypatch.syspath_prepend(path)
monkeypatch.chdir(path)
所有的修改将在测试用例或者fixture
执行完成后撤销。raising
参数表明:当设置/删除操作的目标不存在时,是否上报KeyError
和AttributeError
异常。
1. 修改函数功能或者类属性
使用monkeypatch.setattr()
可以将函数或者属性修改为你希望的行为,使用monkeypatch.delattr()
可以删除测试用例使用的函数或者属性;
参考以下三个例子:
-
在这个例子中,使用
monkeypatch.setattr()
修改Path.home
方法,在测试运行期间,它一直返回的是固定的Path("/abc")
,这样就移除了它在不同平台上的依赖;测试运行完成后,对Path.home
的修改会被撤销;# src/chapter-5/test_module.py from pathlib import Path def getssh(): return Path.home() / ".ssh" def test_getssh(monkeypatch): def mockreturn(): return Path("/abc") # 替换 Path.home # 需要在真正的调用之前执行 monkeypatch.setattr(Path, "home", mockreturn) # 将会使用 mockreturn 代替 Path.home x = getssh() assert x == Path("/abc/.ssh")
-
在这个例子中,使用
monkeypatch.setattr()
结合类,模拟函数的返回对象;假设我们有一个简单的功能,访问一个
url
返回网页内容:# src/chapter-5/app.py from urllib import request def get(url): r = request.urlopen(url) return r.read().decode