使用自动指定的模拟跟踪调用顺序

Tracking order of calls with autospeced mocks

我在使用 Python 3.6 中的 unittest.mock 模块时遇到了一些奇怪的问题。

在我的测试中,我将模拟附加到父模拟,以便能够跟踪它们的调用顺序。

这里有一个玩具示例来说明这个问题:

import unittest
from unittest import mock


def add(a, b):
    return a + b


def div(a, b):
    return a / b


def add_plus_div(a, b):
    return [add(a, b), div(a, b)]


@mock.patch("__main__.add")
@mock.patch("__main__.div")
class MyTests(unittest.TestCase):

    def test_one(self, mock_div, mock_add):

        parent = mock.Mock()
        parent.attach_mock(mock_div, "div")
        parent.attach_mock(mock_add, "add")

        add_plus_div(1, 2)

        parent.assert_has_calls([
            mock.call.add(1, 2),
            mock.call.div(1, 2),
        ])


if __name__ == '__main__':
    unittest.main()

这很好用,并且如您所愿地通过了。

但是,如果您自动指定模拟:

@mock.patch("__main__.add", autospec=True)
@mock.patch("__main__.div", autospec=True)
class MyTests(unittest.TestCase):

    def test_one(self, mock_div, mock_add):

        parent = mock.Mock()
        parent.attach_mock(mock_div, "div")
        parent.attach_mock(mock_add, "add")

        add_plus_div(1, 2)

        parent.assert_has_calls([
            mock.call.add(1, 2),
            mock.call.div(1, 2),
        ])

你失败了:

AssertionError: Calls not found.
Expected: [call.add(1, 2), call.div(1, 2)]
Actual: []

有谁知道为什么 autospecing 会破坏某些东西,以及如何跟踪许多 autospeced 模拟函数的调用顺序?

看起来这是一个已知但长期存在的错误的实例:https://bugs.python.org/issue21478