Cannot use attach_mock with an autospec function mock

烈酒焚心 提交于 2021-02-19 07:27:19

问题


Library module:

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

def bar1(x):
    pass

def bar2(x, y):
    pass

Test module:

# 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"),
        ]
    )

The mocker fixture is from pytest-mock plugin. Execute the MCVE with python -m pytest.

This test fails for weird reasons.

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

Without the autospec it works. Does using autospec break the attach_mock feature? How should the test for foo assert on the order and args of the calls to dependencies bar1 and bar2 without losing their autospec?


回答1:


This was actually a bug in Python. It got fixed in late 2019, patched versions:

  • Python 3.8.2+
  • Python 3.7.5+

The test in original post is now passing on a fixed version. No backport for Python 3.6, which is security only now so will remain bugged forever. 🐛

These are the related PRs and issue tracker links:

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

Patch by Karthikeyan Singaravelan.



来源:https://stackoverflow.com/questions/56367526/cannot-use-attach-mock-with-an-autospec-function-mock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!