1

通常,我关心被测系统对软件的另一部分(我在测试中模拟)进行的确切调用,而不关心这些调用发生的顺序。(例如,因为模拟替换的真实其他部分的最终效果不取决于这些调用的顺序。)

换句话说,我希望我的测试

  • 如果没有进行所有预期的调用,则失败
  • 如果进行了意外调用,则失败(因此unittest.mock.Mock.assert_has_calls还不够)
  • 如果只有调用的顺序发生变化,则不会失败
  • 如果拨打电话的频率低于或高于预期,则失败

所以,我必须检查模拟对象的mock_calls属性。我可以使用 PyHamcrest 以一种通用且合理理解的方式做到这一点contains_inanyorder

#!/usr/bin/env python3
from unittest import TestCase, main
from unittest.mock import Mock, call
from hamcrest import assert_that, contains_inanyorder as contains_in_any_order

class TestMockCalls(TestCase):
    def test_multiple_calls(self):
        m = Mock()
        m('foo')
        m.bar('baz')
        m('foo')
        assert_that(
            m.mock_calls, contains_in_any_order(
                call('foo'),
                call('foo'),
                call.bar('baz'),
            )
        )

if __name__ == '__main__':
    main()

这适用于通过测试,例如上面的测试:

$> ./test_mock_calls.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

当它应该失败时它也会失败(如上所述,例如当您将其中一个更改为时m('foo')m('F00'),但在这种情况下的输出并不像它可能的那样有用:

$> ./test_mock_calls.py
F
======================================================================
FAIL: test_multiple_calls (__main__.TestMockCalls)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./test_mock_calls.py", line 16, in test_multiple_calls
    call.bar('bay'),
AssertionError: 
Expected: a sequence over [, , ] in any order
     but: not matched: 


----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

我可以从中收集的唯一信息(除了哪个测试和哪个断言失败)是总共预期有多少次模拟调用(通过计算方括号之间的逗号),但不是预期的调用,更多重要的是,实际观察到了哪些电话以及多少电话。

这是unittest.mockPyHamcrest 中的错误还是我使用错误?

4

1 回答 1

1

问题是call( _Call) 本身是一种模拟,并且会覆盖__getattr__. 当 hamcrest 开始检查它是​​否具有decribe_to属性时,事情就开始出错了。

我认为,由于这两个模块都在做内省的事情,所以没有一个应该受到责备,并且应该在任何一方实施特殊情况以与另一方很好地配合(可能在 hamcrest 中,因为mock它是一个标准模块)。

用户端的解决方法是:

from unittest.mock import _Call
_Call.describe_to = lambda c, d: d.append(str(c))
于 2018-03-01T10:09:57.860 回答