python - pytest - monkeypatch 关键字参数默认值
问题描述
我想测试一个函数的默认行为。我有以下内容:
# app/foo.py
DEFAULT_VALUE = 'hello'
def bar(text=DEFAULT_VALUE):
print(text)
# test/test_app.py
import app
def test_app(monkeypatch):
monkeypatch.setattr('app.foo.DEFAULT_VALUE', 'patched')
app.foo.bar()
assert 0
输出是hello
;不是我想要的。
一种解决方案是显式传递默认值:app.foo.bar(text=app.foo.DEFAULT_VALUE)
.
但我发现有趣的是,当默认为全局范围时,这似乎不是问题:
# app/foo.py
DEFAULT_VALUE = 'hello'
def bar():
print(DEFAULT_VALUE)
输出是patched
。
为什么会这样?还有比明确传递默认值更好的解决方案吗?
解决方案
函数默认值在函数定义时绑定。
当您在测试代码中时,定义函数的模块已经被导入,并且通过在模块级别常量上的猴子补丁替换默认值已经太晚了。那个名字已经被解析了。
一种解决方法是像这样定义函数:
def bar(text=None):
if text is None:
text = DEFAULT_VALUE
print(text)
现在在函数调用时查找默认值,这意味着模块级别默认的猴子补丁仍然有效。
如果您不喜欢修改函数定义,那么您可以对函数对象本身进行猴子补丁:
monkeypatch.setattr("app.foo.bar.__defaults__", ("test_hello",))
推荐阅读
- pine-script - 松脚本重复信号问题
- ios - 有没有办法创建一个包含 Arm 和 x86 代码的预编译库,并且可以被 macOS、iOS 和 iOS 模拟器调用?
- java - 如何将按钮呈现到 main.dart 文件?另外,有没有什么方法可以在不使用任何按钮的按下()的情况下将参数传递给命名路由?
- javascript - 平滑渲染 - React Native
- r - 循环替换R中字符串/因子变量/向量中的字符
- microsoft-graph-api - 收到validationToken但订阅验证请求超时
- node.js - 错误:监听 EADDRINUSE:地址已在使用 :::5000
- python - Python super() 参数 1 必须是类型,而不是 classobj
- sql - 在 Rails 中搜索匹配确切条件的多对多关系
- flutter - 将滚动条添加到 CustomScollView