2015-12-11 32 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()這個類不是內部的,它的意思是用於這些斷言。

相關問題