Python Unittest Mock assert_has_calls返回对其他Mock的调用



这里有一个简单的例子来说明我的问题。

<标题>代码
class Bar:
def do_a_thing(self):
print('doing a thing')

class BarSupplier:
def get_bar(self) -> Bar:
return Bar()

class Foo:
def __init__(self, bar_supplier: BarSupplier):
self.bar_supplier = bar_supplier
def do_foo(self):
self.bar_supplier.get_bar().do_a_thing()
<标题>测试
from unittest import TestCase
from unittest.mock import MagicMock, call
from calls_example import Foo

class TestCallsExample(TestCase):
def test_once(self):
bar_supplier = MagicMock()
bar_supplier.get_bar.return_value = MagicMock()
foo = Foo(bar_supplier)
foo.do_foo()
bar_supplier.get_bar.assert_has_calls([
call(),
])
def test_twice(self):
bar_supplier = MagicMock()
bar_supplier.get_bar.return_value = MagicMock()
foo = Foo(bar_supplier)
foo.do_foo()
foo.do_foo()
bar_supplier.get_bar.assert_has_calls([
call(),
call()
])
<标题>

结果第一个测试通过。

第二个测试失败,有以下异常:

Failure
Traceback (most recent call last):
...
AssertionError: Calls not found.
Expected: [call(), call()]
Actual: [call(), call().do_a_thing(), call(), call().do_a_thing()]

这感觉真的很奇怪的行为-我断言对bar_supplier模拟上的get_bar方法的调用,但随后调用列表包括对由get_bar方法返回的不同模拟的调用。

我确信这是一个误解而不是一个错误,但是我如何才能最好地避免在我的呼叫列表中得到那些.do_a_thing()呼叫?

这是因为.get_bar()的相同mock总是随后调用.do_a_thing(),如文档所示:

assert_has_calls(calls, any_order=False)

断言mock已被指定的调用调用。mock_calls检查列表中是否有呼叫。

其中mock_calls不仅包括对自身的调用:

mock_calls

mock_calls记录所有对模拟对象的调用,其方法,魔术方法和返回值模拟.

解决方案1

您可以使用any_order=True设置assert_has_calls,如文档所示:

如果any_order为假,则调用必须顺序。在指定的调用之前或之后可以有额外的调用。

如果any_order为真,则调用可以在任意顺序,但它们必须都出现在mock_calls中。

所以改变:

bar_supplier.get_bar.assert_has_calls([
call(),
call()
])

:

bar_supplier.get_bar.assert_has_calls([
call(),
call()
],
any_order=True)

解决方案2

另一种选择是检查call_args_list:

assert bar_supplier.get_bar.call_args_list == [
call(),
call()
]

最新更新