不能将 attach_mock 与 autospec 函数模拟一起使用

Cannot use attach_mock with an autospec function mock

库模块:

# mod.py
def foo():
    bar1("arg1")
    bar2("arg2x", "arg2y")

def bar1(x):
    pass

def bar2(x, y):
    pass

测试模块:

# test_mod.py
from mod import foo

def test_foo(mocker):
    mock = mocker.MagicMock()
    mock.attach_mock(mocker.patch("mod.bar1"), "b1")
    mock.attach_mock(mocker.patch("mod.bar2", autospec=True), "b2")
    foo()
    mock.assert_has_calls(
        [
            mocker.call.b1("arg1"),
            mocker.call.b2("arg2x", "arg2y"),
        ]
    )

mocker 夹具来自 pytest-mock plugin. Execute the MCVEpython -m pytest

此测试失败 weird reasons

E       AssertionError: Calls not found.
E       Expected: [call.b1('arg1'), call.b2('arg2x', 'arg2y')]
E       Actual: [call.b1('arg1')]

没有 autospec 就可以了。使用 autospec 会破坏 attach_mock 功能吗? foo 的测试应该如何在调用依赖项 bar1bar2 order 和 args 上断言而不丢失它们自动规格?

这实际上是 Python 中的错误。它在 2019 年底得到修复,补丁版本:

原来post中的测试现在通过了一个固定版本。 Python 3.6 没有向后移植,现在是 security only,因此将永远存在漏洞。

这些是相关的 PR 和问题跟踪器链接:

bpo-21478: Autospec functions should propagate mock calls to parent

bpo-21478: Record calls to parent when autospecced objects are used as child with attach_mock

bpo-38473: Handle autospecced functions and methods used with attach_mock

Karthikeyan Singaravelan 的补丁。