`pytest` 的 `mocker` 是从哪里来的?

3

我正在跟随pytest-mock的这个小教程/博客。 我无法理解mocker是如何工作的,因为没有导入它 - 特别是函数声明def test_mocking_constant_a(mocker):

import mock_examples.functions
from mock_examples.functions import double

def test_mocking_constant_a(mocker):
    mocker.patch.object(mock_examples.functions, 'CONSTANT_A', 2)
    expected = 4  
    actual = double()  # now it returns 4, not 2

    assert expected == actual

一些奇怪的事情发生了,mocker 具有 pytest-mocker.mocker 的属性/函数,特别是 mocker.patch.object。但是如果没有导入语句,这怎么可能呢?


3
mocker是一种在插件中定义的fixture。这些fixture会在pytest启动时加载,并像所有fixture一样按名称查找。 - MrBean Bremen
@MrBeanBremen,请把那个链接和摘要变成回答,它很有帮助。 - WestCoastProjects
1个回答

4
mocker 变量是 Pytest 的 fixture,与使用导入不同,fixture 使用依赖注入提供 - 也就是说,Pytest 负责为您创建 mocker 对象,并在运行测试时将其提供给测试函数。
Pytest-mock 在这里定义 "mocker" fixture (链接),使用 Pytest 的 fixture 装饰器。在这里,fixture 装饰器被用作常规函数,这是一种略微不寻常的方式。使用 fixture 装饰器的更典型的方式可能是这样的:
@pytest.fixture()
def mocker(pytestconfig: Any) -> Generator[MockerFixture, None, None]:
    """
    Return an object that has the same interface to the `mock` module, but
    takes care of automatically undoing all patches after each test method.
    """
    result = MockerFixture(pytestconfig)
    yield result
    result.stopall()
fixture 装饰器会将 "mocker" 函数与 Pytest 注册,当 Pytest 运行一个名为 "mocker" 的参数的测试时,它会自动插入 "mocker" 函数的结果。
这是因为 Pytest 使用 Python 的内省特性来查看参数列表(包括名称)在调用测试函数之前。它将已注册的 fixture 名称与参数名称进行比较,如果匹配,则将相应的对象提供给测试函数的该参数。

1
现在已经过了午夜,我太累了,无法享用这种饮料。但我相信对于更加清醒和有奖励性的人来说,这是有意义的。 - WestCoastProjects
2
完全可以。如果您对此感到好奇,它使用Python的内省功能,在调用测试函数之前检查它。这允许pytest获取所需参数的名称列表,并在已加载的fixture字典中查找名称。 - spectras
1
@ spectras 感谢您的澄清。我在我的回答中添加了一个关于名称内省的段落。 - Jack Taylor
我曾经是一个Google Guice的忠实粉丝/用户。我甚至不知道Python也支持DI。 - WestCoastProjects

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接