简体   繁体   English

在同一模块中使用 unittest.mock 的补丁,通过“__main__.imported_obj”打补丁时得到“没有属性”

[英]Using unittest.mock's patch in same module, getting “does not have the attribute” when patching via “__main__.imported_obj”

I have what should've been a simple task, and it has stumped me for a while.我有一个应该是简单的任务,它让我难了一段时间。 I am trying to patch an object imported into the current module.我正在尝试patch导入到当前模块中的 object。

Per the answers to Mock patching from/import statement in Python根据Python 中的 Mock patching from/import 语句的答案

I should just be able to patch("__main__.imported_obj") .我应该能够patch("__main__.imported_obj") However, this isn't working for me.但是,这对我不起作用。 Please see my below minimal repro (I am running the tests via pytest ):请看我下面的最小复制(我正在通过pytest运行测试):

Minimal Repro最小复制

This is run using Python 3.8.6.这是使用 Python 3.8.6 运行的。

from random import random
from unittest.mock import patch

import pytest

@pytest.fixture
def foo():
    with patch("__main__.random"):
        return

def test(foo) -> None:
    pass

When I run this code using PyCharm, I get an AttributeError :当我使用 PyCharm 运行此代码时,我得到一个AttributeError

AttributeError: <module '__main__' from '/Applications/PyCharm.app/Contents/plugins/python/helpers/pycharm/_jb_pytest_runner.py'> does not have the attribute 'random'

Furthermore, when I enter debugger mode in the line before the with patch , I see the attribute __main__ is not defined.此外,当我在with patch之前的行中进入调试器模式时,我看到属性__main__没有定义。 I am not sure if it needs to be defined for patch to work its magic.我不确定是否需要定义patch才能发挥其魔力。

NOTE: I know I can use patch.object and it becomes much easier.注意:我知道我可以使用patch.object并且它变得更加容易。 However, I am trying to figure out how to use patch in this question.但是,我试图弄清楚如何在这个问题中使用patch

Research研究

Unable to mock open, even when using the example from the documentation 即使使用文档中的示例,也无法模拟打开

This question is related because it's both a similar error message and use case.这个问题是相关的,因为它既是类似的错误消息,也是用例。 Their solution was to use builtins instead of __main__ , but that's because they were trying to patch a built-in function ( open ).他们的解决方案是使用内置函数而不是__main__ ,但那是因为他们试图patch内置builtins ( open )。

You are assuming that the module the test is running in is __main__ , but that would only be the case if it were called via main .您假设运行测试的模块是__main__ ,但只有通过main调用它时才会出现这种情况。 This is usually the case if you are using unittest .如果您使用的是unittest ,通常就是这种情况。 With pytest, the tests live in the module they are defined in.使用 pytest,测试位于定义它们的模块中。

You have to patch the current module, the name of which is accessible via __name__ , instead of assuming a specific module name:您必须修补当前模块,其名称可通过__name__访问,而不是假设特定的模块名称:

from random import random
from unittest.mock import patch

import pytest

@pytest.fixture
def foo():
    with patch(__name__ + ".random"):
        yield

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM