【问题标题】:How to assert member calls?如何断言成员调用?
【发布时间】:2021-09-27 21:04:46
【问题描述】:

由于MagicMock 实例的所有成员也是MagicMock 实例,我想我可以只模拟顶级对象,而不必模拟调用链中的每个成员。然后我可以简单地询问我的原始模拟是否以某种方式调用了它的任何成员,例如assert_called。当我尝试这个时,调用列表确实看到了对孩子的调用,但是用于测试它们的断言方法是什么?

例如:

from unittest.mock import MagicMock

# Mock an object
foo = MagicMock()

# Try calling a child
foo.bar().baz()

# foo clearly registers the calls to its child...
print(foo.mock_calls)

# ...but how do I assert them?
foo.bar.assert_called()
foo.bar.baz.assert_called()

这不起作用:

$ python assert_member_calls.py
[call.bar(), call.bar().baz()]
[call.bar(), call.bar().baz()]
Traceback (most recent call last):
  File "/(...)/assert_member_calls.py", line 14, in <module>
    foo.bar.baz.assert_called()
  File "/(...)/python3.9/unittest/mock.py", line 876, in assert_called
    raise AssertionError(msg)
AssertionError: Expected 'baz' to have been called.

我知道一种解决方案是基本上为每个属性创建一个模拟,因此除了foo,还要显式模拟barbaz 以及它们的返回值。但这似乎是不必要的乏味。如果foo 是模拟,那么barbar()bazbaz() 也已经自动模拟。我不应该恢复一个新的模拟和补丁foo.bar.baz(这是一个模拟开始),这样我就可以处理mock_baz.assert_called()。为了支持我的想法,显然foo 的调用列表包含call.bar().baz() -- 没有可以做到assert that call.bar().baz() was called 的方法吗?

【问题讨论】:

  • 与问题本身无关,但必须访问foo.bar().baz()[...] 并不理想——也许您可以改进bar 接口,或创建foo.get_baz_results 方法以使测试更容易。重构代码以使其更易于测试(并在以后理解)是测试帮助您编写更好代码的方法之一。
  • @jfaccioni 绝对!然而,在这种情况下,我实际上是在使用外部库,因此更改接口是不切实际的。

标签: python unit-testing mocking pytest pytest-mock


【解决方案1】:

这是您断言中的一个简单错误。所写的第一个断言是可以的。但是第二个断言应该是 foo.bar().baz.assert_called(),因为 baz 是在 返回值 foo.bar() 上调用的,而不是直接在 foo.bar 本身上调用的。

这些断言有效:

foo.bar.assert_called()
foo.bar().baz.assert_called()

做同样事情的其他方式:

foo.bar.assert_called()
foo.bar.return_value.baz.assert_called()

【讨论】:

    【解决方案2】:

    您可以检查每个模拟对象的属性called。 (使用unittest,您似乎正在使用),您可以使用以下代码:

    # ...but how do I assert them?
    def test_called(self):
        self.assertTrue(foo.bar.called)
        self.assertTrue(foo.bar().baz.called)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-04
      • 1970-01-01
      相关资源
      最近更新 更多