Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python mock call_args_list为参数断言解包元组_Python_Unit Testing_Python Unittest_Python Unittest.mock - Fatal编程技术网

Python mock call_args_list为参数断言解包元组

Python mock call_args_list为参数断言解包元组,python,unit-testing,python-unittest,python-unittest.mock,Python,Unit Testing,Python Unittest,Python Unittest.mock,我在处理Mock.call\u args\u 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 i

我在处理
Mock.call\u args\u 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'))

我想知道是否有更好的方法来解包mock对象上的call_args_列表,以便做出我的断言。这个循环是有效的,但感觉必须有一个更直接的方法。

一个更好的方法可能是建立您自己的预期调用,然后使用直接断言:

>>> 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)
>>> 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)
>>类任意后缀(对象):
...     定义(自身、其他):
...         尝试:
...             返回其他.startswith('PASS')
...         除例外情况外:
...             返回错误
...        
>>>f=Mock()
>>>f(‘通行证和其他东西’)
>>>f(‘传递更多内容’)
>>>f(“通过废话废话不在乎”)
>>>预期的_调用=[call(AnySuffix())]*3
>>>f.assert_有_调用(预期_调用)
以及故障模式的示例:

>>> 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: []
>>Mock().assert\u有\u调用(预期的\u调用)
AssertionError:找不到调用。
应为:[调用(),
call(),
调用()]
实际:[]

我认为这里的许多困难都与“call”对象的处理有关。它可以被认为是一个具有两个成员的元组
(args,kwargs)
,因此通常最好将其解包:

args, kwargs = call
解包后,就可以分别对args和kwargs进行断言(因为一个是元组,另一个是dict)

请注意,有时简洁是没有帮助的(例如,如果有错误):


我认为这实际上取决于你试图做出什么样的断言。是否只检查位置参数?您正在尝试检查位置参数和关键字参数吗?您是要检查关键字本身还是通过关键字参数传递的值?e、 g.如果您只想检查第一个位置参数是否以
'PASS'
开头,那么
self.assertTrue(调用[0][0]。startswith('PASS'))
应该在不使用内部2个循环的情况下执行此操作。这只有在OP确实知道每个调用应该是什么样子时才有效。基于这个问题,OP似乎只知道每个参数的第一部分应该是什么样子(这很奇怪……但是嘿……)嗯,
call
只是一个元组,所以它仍然可以修改以工作。我将进行编辑以显示如何…更重要的是,我不希望我的测试关心参数第一部分后面的内容,因为后面的内容非常冗长且变化很大,因此让测试对其进行断言变得非常乏味。我添加了一个示例以显示如何模糊匹配调用。然而,作为一个警示故事,如果你不能准确预测测试中调用的结果,这通常是一个警告信号,表明有些东西本不应该被嘲笑。@wim——是的。我见过很多次使用你的方式,但总觉得作为一个录制/回放类型的框架太难了。python单元测试有记录/回放框架,但我从未真正考虑过
unittest.mock
是其中之一:-)哦,伙计
args,kwargs=call
是所有
调用args\u列表
黑客的线索。非常感谢。
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)