簡體   English   中英

Python模擬call_args_list拆包元組以聲明參數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM