2012-02-05 86 views
9

單元測試應測試功能並嘗試對實現細節不知情。 Mock.assert_called_with()是一個方便的功能,但它比較*args*args**kwargs**kwargs。因此:使Mock.assert_called_with()與args vs kwargs無關

# class to be mocked during test 
class SomeClass(): 
    def func(self,a,b,c=5): 
     # ... 

# code under test 
somaclass_instance.func(1,b=2,c=3) 

# test code that works 
someclass_mock.func.assert_called_with(1,b=2,c=3) 

# test code that won't work 
someclass_mock.func.assert_called_with(1,2,c=3) 
someclass_mock.func.assert_called_with(a=1,b=2,c=3) 

有沒有辦法讓這*args的地方爲**kwargs在調用func,這實在是一個實現細節所用的具體內容,將被忽略概括呢?

+0

我不是100%肯定我明白你的問題,但你可以通過*指定參數和** kwargs在同一個函數調用,或者,由於ARG遊戲類型元組和kwargs是類型的字典,你可能會能夠編寫一個封裝函數,將輸入規範化爲一個你確定可以工作的函數。 – 2012-02-05 21:20:28

+1

現在是否有任何模擬框架這樣做?我的測試不應該因爲有人決定在某個時候將位置參數改變爲關鍵字參數而失敗。但是,這個問題是我見過這個問題的唯一一次。模擬已經支持規範對象,所以這應該是可能的? – jan 2015-02-20 15:23:56

回答

5

文件功能請求模擬。

根本的問題是,沒有進入真正的函數/類模擬無法知道的關鍵字參數的順序的方法,即調用call(a=1, b=2)call(b=2, a=1)看起來相同嘲笑,而調用call(1, 2)call(2, 1)沒有。

如果要概括模擬,您將需要通過調用原型或代替原型的功能,如:

amock.afunc.assert_called_with(1, 2, c=3, __prototype__=lambda a=None, b=None, c=None: None) 
1

因爲Python 3.4,就像你想要的,聲稱對特定呼叫簽名在使用spec創建可調用Mock時自動進行標準化,對於使用自動specifying時的對象方法進行標準化。

the documentation of the Mock class最末端:匹配 呼叫的模擬時

其用一個規範(或spec_set)創建的調用模擬將 內省規範對象的簽名。因此,它可以匹配的實際調用的參數 不管他們是否在位置上通過或名稱:

>>> def f(a, b, c): pass 
... 
>>> mock = Mock(spec=f) 
>>> mock(1, 2, c=3) 
<Mock name='mock()' id='140161580456576'> 
>>> mock.assert_called_with(1, 2, 3) 
>>> mock.assert_called_with(a=1, b=2, c=3) 

這適用於assert_called_with(),assert_called_once_with(), assert_has_calls()和assert_any_call()。當自動調用時,它將 也適用於模擬對象上的方法調用。

在版本3.4中進行了更改:在specified和自動描述的模擬對象上添加了簽名反省。

相關問題