[英]Python mock call_args_list unpacking tuples for assertion on arguments
我在处理Mock.call_args_list
返回的嵌套元组时遇到一些麻烦。
def test_foo(self):
def foo(fn):
fn('PASS and some other stuff')
f = Mock()
foo(f)
foo(f)
foo(f)
for call in f.call_args_list:
for args in call:
for arg in args:
self.assertTrue(arg.startswith('PASS'))
我想知道是否有更好的方法可以在模拟对象上解压缩该call_args_list,以便进行断言。 此循环有效,但感觉必须有更直接的方法。
我认为,这里的许多困难都笼罩在处理“通话”对象中。 可以将其视为具有2个成员(args, kwargs)
的元组,因此通常将其拆包是很不错的:
args, kwargs = call
解压缩后,就可以分别对args和kwargs进行断言(因为一个是元组,另一个是dict)
def test_foo(self):
def foo(fn):
fn('PASS and some other stuff')
f = Mock()
foo(f)
foo(f)
foo(f)
for call in f.call_args_list:
args, kwargs = call
self.assertTrue(all(a.startswith('PASS') for a in args))
请注意,有时简洁性无济于事(例如,如果有错误):
for call in f.call_args_list:
args, kwargs = call
for a in args:
self.assertTrue(a.startswith('PASS'), msg="%s doesn't start with PASS" % a)
更好的方法可能是建立您自己的预期调用,然后使用直接断言:
>>> from mock import call, Mock
>>> f = Mock()
>>> f('first call')
<Mock name='mock()' id='31270416'>
>>> f('second call')
<Mock name='mock()' id='31270416'>
>>> expected_calls = [call(s + ' call') for s in ('first', 'second')]
>>> f.assert_has_calls(expected_calls)
请注意,调用必须是顺序的,如果您不希望这样,则将any_order
kwarg覆盖到断言。
另请注意,允许在指定呼叫之前或之后进行额外的呼叫。 如果您不希望这样做,则需要添加另一个断言:
>>> assert f.call_count == len(expected_calls)
在谈到mgilson的评论时,下面是一个创建虚拟对象的示例,您可以将其用于通配符相等性比较:
>>> class AnySuffix(object):
... def __eq__(self, other):
... try:
... return other.startswith('PASS')
... except Exception:
... return False
...
>>> f = Mock()
>>> f('PASS and some other stuff')
<Mock name='mock()' id='28717456'>
>>> f('PASS more stuff')
<Mock name='mock()' id='28717456'>
>>> f("PASS blah blah don't care")
<Mock name='mock()' id='28717456'>
>>> expected_calls = [call(AnySuffix())]*3
>>> f.assert_has_calls(expected_calls)
以及失败模式的示例:
>>> Mock().assert_has_calls(expected_calls)
AssertionError: Calls not found.
Expected: [call(<__main__.AnySuffix object at 0x1f6d750>),
call(<__main__.AnySuffix object at 0x1f6d750>),
call(<__main__.AnySuffix object at 0x1f6d750>)]
Actual: []
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.