Python 如何在pytest中使用monkeypatch或mock删除库?

Python 如何在pytest中使用monkeypatch或mock删除库?,python,pytest,monkeypatching,pytest-mock,Python,Pytest,Monkeypatching,Pytest Mock,如果我的库中有一个contribextra,其中包含依赖项(比如requests),我希望用户必须安装它才能访问CLI API,但是我在CI中的测试期间安装了contrib extra,那么我如何在测试期间使用它来删除依赖项,以确保检测正确 例如,如果contribextra将额外安装请求,那么我希望用户必须这样做 $ python -m pip install mylib[contrib] 然后能够在命令行中使用一个CLI API $ mylib contrib myfunction 其中

如果我的库中有一个
contrib
extra,其中包含依赖项(比如
requests
),我希望用户必须安装它才能访问CLI API,但是我在CI中的测试期间安装了contrib extra,那么我如何在测试期间使用它来删除依赖项,以确保检测正确

例如,如果
contrib
extra将额外安装
请求
,那么我希望用户必须这样做

$ python -m pip install mylib[contrib]
然后能够在命令行中使用一个CLI API

$ mylib contrib myfunction
其中
myfunction
使用
请求
依赖项

#mylib/src/mylib/cli/contrib.py
导入点击
尝试:
导入请求
除ModuleNotFoundError外:
pass可能应该发出警告,但这只是一个例子
# ...
@单击.group(name=“contrib”)
def cli():
"""
控制实验操作。
"""
@cli.command()命令
@单击.argument(“示例”,默认值=“-”)
def myfunction(示例):
requests.get(示例)
# ...
如何在我的
pytest
测试中模拟或monkeypatch out
请求
,以便我可以确保用户在执行
ModuleNotFoundError
时会正确地收到警告

$ python -m pip install mylib
$ mylib contrib myfunction

??在阅读了pytest标签上的一些其他问题后,我仍然不知道如何做,所以我在这里问。

我最终做了什么,我已经确认这是一个合理的方法,就是模拟额外的依赖性(这里
请求
)在
sys.modules
中将其设置为
None
,然后重新加载需要使用
请求的模块,则不存在。
我测试是否存在实际投诉,即使用
caplog
导入的
请求不存在

这是我目前正在使用的测试(更改名称以匹配上面问题中的玩具示例问题)

导入mylib
导入系统
导入日志记录
导入pytest
从unittest导入模拟
从导入lib导入重新加载
从导入lib导入模块
# ...
def测试缺失额外费用(caplog):
使用mock.patch.dict(系统模块):
系统模块[“请求”]=无
如果系统模块中有“mylib.contrib.utils”:
重新加载(系统模块[“mylib.contrib.utils”])
其他:
导入_模块(“mylib.cli”)
使用caplog.at_级别(logging.ERROR):
#第2行和第3行检查mylib抛出的错误消息
排队[
“请求导入已停止;sys.modules中无请求”,
“使用mylib.contrib.utils.download需要安装contrib extra”,
“请使用:python-m pip install mylib[contrib]安装”,
]:
在caplog.text中断言行
caplog.clear()
我应该注意到这实际上是@hoefling链接到上面(在我解决这个问题之后,但在我开始发布这个之前发布)所提倡的

如果人们有兴趣在实际的图书馆看到这一点,c.f.以下两个PRs:

注: 安东尼·索蒂尔警告说

reload()
可能有点不确定——我会小心使用它(对旧模块有旧引用的东西会继续存在,有时它会引入新的单态副本(双态?三态?)——我已经跟踪了许多测试污染问题到
reload()


因此,如果我实施了更安全的替代方案,我将修改此答案。

是否回答了您的问题?谢谢您的回答,但也许我应该在pytest测试中指定我使用pytest控制台脚本中的脚本运行器装置,以确保我实际测试了CLI功能。我同意在大多数情况下,类似的方法都会奏效,但我需要解决的似乎是跑步者的状态问题。这是否回答了你的问题?也许是为了澄清-但是
monkeypatch.setitem
可能更值得依赖?从这条推特帖子中,Anthony会说不:“我个人的意见是永远不要使用monkeypatch夹具,因为模仿范围没有得到很好的定义/控制。”