[英]Python Unittest Mock assert_has_calls returning calls to other mocks
Here's a toy example that illustrates my problem.这是一个说明我的问题的玩具示例。
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()
])
The first test passes.第一个测试通过。
The second test fails, with the following exception:第二个测试失败,但出现以下异常:
Failure
Traceback (most recent call last):
...
AssertionError: Calls not found.
Expected: [call(), call()]
Actual: [call(), call().do_a_thing(), call(), call().do_a_thing()]
This feels like really strange behaviour - I'm asserting about calls to the get_bar
method on the bar_supplier
mock, but then the calls list includes calls to a different mock which is returned by the get_bar
method.这感觉真的很奇怪——我断言调用
bar_supplier
mock 上的get_bar
方法,但随后调用列表包括对get_bar
方法返回的不同 mock 的调用。
I'm sure this is a misunderstanding rather than a bug, but how can I best avoid getting those .do_a_thing()
calls in my list of calls?我确信这是一种误解而不是错误,但是我怎样才能最好地避免在我的调用列表中收到那些
.do_a_thing()
调用?
It is because the same mock for .get_bar()
always subsequently calls .do_a_thing()
which as documented :这是因为
.get_bar()
的相同模拟总是随后调用.do_a_thing()
,如记录的那样:
assert_has_calls(calls, any_order=False)
assert the mock has been called with the specified calls.
断言已使用指定的调用调用模拟。 The
mock_calls
list is checked for the calls.检查
mock_calls
列表中的调用。
Wherein mock_calls includes not just the calls to itself:其中mock_calls 不仅包括对自身的调用:
mock_calls
mock_calls records all calls to the mock object , its methods , magic methods and return value mocks .
mock_calls 记录了对 mock object及其方法、魔术方法和返回值 mocks的所有调用。
You can use the any_order=True
setting for assert_has_calls which as documented:您可以对assert_has_calls使用
any_order=True
设置,如文档所述:
If
any_order
is false then the calls must be sequential .如果
any_order
为 false 则调用必须是顺序的。 There can be extra calls before or after the specified calls.在指定的调用之前或之后可以有额外的调用。
If
any_order
is true then the calls can be in any order , but they must all appear in mock_calls.如果
any_order
为真,则调用可以按任何顺序进行,但它们必须全部出现在 mock_calls 中。
So change:所以改变:
bar_supplier.get_bar.assert_has_calls([
call(),
call()
])
To:到:
bar_supplier.get_bar.assert_has_calls([
call(),
call()
],
any_order=True)
An alternative is checking call_args_list instead:另一种方法是检查call_args_list :
assert bar_supplier.get_bar.call_args_list == [
call(),
call()
]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.