2015-12-11 31 views
1

假设我们有一个功能f(x,y)和其他功能检查是否功能已被使用不同的参数调用多次

def g(): 
     # ... 
     f(i,j) # i,j vary and f is called multiple times 
     # ... 

我们要编写一个单元测试,检查f是否调用次数,并与数正确的参数。

def test_g(): 
     with patch('mymodule.f') as function: 
      assert function.gacs.call_count == correct_no_calls 

function.assert_called_with(...) 

但这只是指最后一次通话。因此,假设g调用f(1,2),然后f(2,3),function.assert_called_with(1,2)False

此外,存在

function.call_args_list 

这产生call对象与右参数的列表。将此列表与call比较,我们在单元测试中创建的对象感觉像是一件非常讨厌的事情。 call看起来像是模拟库的内部类。

有没有更好的方法来做到这一点?我使用这个设置来测试apply函数的并行执行。

回答

1

即使@ MartinPieters的回答是正确的我认为这不是最好的办法。模拟提供assert_has_calls做这种职责。

您的测试可能是:

function.assert_has_calls([mock.call(1, 2), mock.call(2, 3)]) 

mock.call是一个辅助类做这些行业的工作经验。

注重这是一个呼叫,是指通话清单应在通话清单和不相等。为了解决这个问题,我通常定义自己的助手assert_is_calls()如下

def assert_is_calls(m, calls, any_order=False): 
    assert len(m.mock_calls) == len(calls) 
    m.assert_has_calls(calls, any_order=any_order) 

那一份简历例子

>>> import mock 
>>> f = mock.Mock() 
>>> f(1) 
<Mock name='mock()' id='139836302999952'> 
>>> f(2) 
<Mock name='mock()' id='139836302999952'> 
>>> f.assert_has_calls([mock.call(1), mock.call(2)]) 
>>> f.assert_has_calls([mock.call(2), mock.call(1)]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/home/damico/.local/lib/python2.7/site-packages/mock/mock.py", line 969, in assert_has_calls 
    ), cause) 
    File "/home/damico/.local/lib/python2.7/site-packages/six.py", line 718, in raise_from 
    raise value 
AssertionError: Calls not found. 
Expected: [call(2), call(1)] 
Actual: [call(1), call(2)] 
>>> f.assert_has_calls([mock.call(2), mock.call(1)], any_order=True) 
>>> f(3) 
<Mock name='mock()' id='139836302999952'> 
>>> f.assert_has_calls([mock.call(2), mock.call(1)], any_order=True) 
>>> f.assert_has_calls([mock.call(1), mock.call(2)]) 
>>> assert len(f.mock_calls)==2 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AssertionError 
>>> assert len(f.mock_calls)==3 
>>> def assert_is_calls(m, calls, any_order=False): 
... assert len(m.mock_calls) == len(calls) 
... m.assert_has_calls(calls, any_order=any_order) 
... 
>>> assert_is_calls(f, [mock.call(1), mock.call(2), mock.call(3)]) 
>>> assert_is_calls(f, [mock.call(1), mock.call(3), mock.call(2)]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in assert_is_calls 
    File "/home/damico/.local/lib/python2.7/site-packages/mock/mock.py", line 969, in assert_has_calls 
    ), cause) 
    File "/home/damico/.local/lib/python2.7/site-packages/six.py", line 718, in raise_from 
    raise value 
AssertionError: Calls not found. 
Expected: [call(1), call(3), call(2)] 
Actual: [call(1), call(2), call(3)] 
>>> assert_is_calls(f, [mock.call(1), mock.call(3), mock.call(2)], True) 
>>> assert_is_calls(f, [mock.call(1), mock.call(3)], True) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in assert_is_calls 
AssertionError 
>>> 
+0

'assert_has_calls'不关心*所有*的呼叫。你可以给它一个子集,它会返回true。如果你想断言这些只是** **电话,那么你需要使用我的方法。 –

+0

你的包装函数,默认为'any_order = False',它有效地做和'assertEquals(m.mock_calls,调用)'一样的东西,那么为什么这个额外的函数呢?该功能不会为你购买任何额外的东西.. –

+0

@MartijnPieters是的,这是因为我提到我自己的helper assert_is_calls()关心所有的调用....我现在正在阅读你的新评论:这完全是关于命名。这是明确你想要声明的。无论如何,您可以精确选择您想要做的事情,查看订单与否,检查确切的所有电话或只是一个子集。 –

3

测试如果Mock().mock_calls list等于mock.call() objects列表您提供:

self.assertEquals(function.mock_calls, [ 
    mock.call(1, 2), 
    mock.call(2, 3), 
]) 

这给你精确的控制,需要的顺序和调用匹配的数量。

mock.call()这个类不是内部的,它的意思是用于这些断言。

相关问题