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

马修·费克特(Matthew Feickert)

如果我的图书馆有一个contrib带有依赖于它(比如额外的requests),我希望用户必须安装有访问CLI API,但我在我的CI测试中如何使用安装的contrib额外pytestMonkeyPatch去除测试过程中的依赖性以确保我的检测正确吗?

例如,如果contrib额外安装额外的设备requests,那么我希望用户必须这样做

$ python -m pip install mylib[contrib]

然后可以在命令行中使用看起来像这样的CLI API

$ mylib contrib myfunction

在哪里myfunction使用requests依赖

# mylib/src/mylib/cli/contrib.py
import click
try:
    import requests
except ModuleNotFoundError:
    pass # should probably warn though, but this is just an example

# ...

@click.group(name="contrib")
def cli():
    """
    Contrib experimental operations.
    """

@cli.command()
@click.argument("example", default="-")
def myfunction(example):
   requests.get(example)
   # ...

我怎么嘲笑或猴补丁 requests在我pytest的测试,这样我可以确保用户将正确地与相处的警告ModuleNotFoundError,如果他们只是做

$ python -m pip install mylib
$ mylib contrib myfunction

在阅读了pytest标签上的其他问题之后,我仍然不知道我该怎么做,所以我在这里问。

马修·费克特(Matthew Feickert)

我最终做了这项工作,并通过Anthony Sottile确认了一种合理的方法,是requests通过将它设置为Noneinsys.modules并重新加载将加载的模块来嘲笑不存在额外的依赖项(在此处。需要使用requests我测试requests了使用不存在要导入的实际投诉caplog

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

import mylib
import sys
import logging
import pytest
from unittest import mock
from importlib import reload
from importlib import import_module

# ...

def test_missing_contrib_extra(caplog):
    with mock.patch.dict(sys.modules):
        sys.modules["requests"] = None
        if "mylib.contrib.utils" in sys.modules:
            reload(sys.modules["mylib.contrib.utils"])
        else:
            import_module("mylib.cli")

    with caplog.at_level(logging.ERROR):
        # The 2nd and 3rd lines check for an error message that mylib throws
        for line in [
            "import of requests halted; None in sys.modules",
            "Installation of the contrib extra is required to use mylib.contrib.utils.download",
            "Please install with: python -m pip install mylib[contrib]",
        ]:
            assert line in caplog.text
        caplog.clear()

我应该注意到,这实际上是@Abhyudai对“使用pytestinit .py中测试导入可选依赖项:Python 3.5 /3.6的行为有所不同”的答案所倡导的,@ hoefling链接到上面(在我解决了此问题后发布,在我发布此信息之前)。

如果人们有兴趣在实际的库中看到此内容,请参考以下两个PR:

注意:Anthony Sottile警告说

reload() 可能有点不确定-我会小心一点(对旧模块有旧引用的东西会继续存在,有时它会引入单例(doubletons?Tripletons?)的新副本)-我追踪了很多-测试污染问题 reload()

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Pytest無法在monkeypatch中使用fixture

如何使用pytest monkeypatch修补类

如何使用pytest在“设置”方法中使用Monkeypatch进行单元测试?

如何在Django中使用pytest?

如何在子进程中使用 pytest?

如何在 Python 中使用monkeypatch 模拟不属于任何类的函数?

pytest:使用假设时的monkeypatch

如何在CppUnitTestFramework中使用Google Mock

使用pytest-mock在python中使用SQLalchemy模拟数据库调用

如何在通用存储库(Entity Framework)的include属性中使用软删除?

如何在MongoDB中使用Hibernate OGM删除数据库或集合

如何在SQL Server中使用查询删除特定的数据库权限?

如何在Codeigniter中使用AJAX和PHP从MySQL数据库删除记录

如何在 nodejs(express) 中使用 sequelize(sqlite) 作为数据库创建删除方法

如何在 Laravel 中使用 30 分钟撤消功能从数据库中删除行

如何在Pytest中使用灯具的替代参数?

如何在conftest.py中使用pytest修补环境?

如何在多个异常中使用pytest.raises?

如何在批量pytest执行中使用对象的__subclasses __()方法?

如何在基类中使用@ pytest.mark?

如何在 tox python env 中使用 pytest 和 pyclip?

如何在Ros中使用Qt库

如何在c#中使用库

如何在cmake中使用FFTW库?

如何在typeorm中使用存储库?

如何在静态库中使用lto?

如何在Dart中使用JavaScript库

如何在Rails中使用googlecharts库?

如何在Laravel中使用COM库?