2012-02-05 16 views
9

I test unitari dovrebbero testare la funzionalità e cercare di essere agnostici ai dettagli di implementazione. Mock.assert_called_with() è una funzione comoda, tuttavia AFAIK confronta *args a *args e **kwargs a **kwargs. Pertanto:rendere Mock.assert_called_with() agnostico a 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) 

c'è un modo per generalizzare questo modo che le specifiche di cui *args dove utilizzati come **kwargs nella chiamata a func, che in realtà è un dettaglio di implementazione, verranno ignorati?

+0

Io non sono sicuro al 100% di aver capito la tua domanda, ma potresti passare * args e ** kwargs nella stessa chiamata di funzione, oppure, poiché gli argomenti sono di tipo tupla, e kwargs sono dicts, potresti essere in grado di scrivere una funzione wrapper che normalizza l'input a uno che sei sicuro di poter funzionare. –

+1

C'è qualche finta struttura ormai che fa questo? I miei test non dovrebbero fallire solo perché qualcuno ha deciso di cambiare un argomento posizionale in un argomento di parole chiave ad un certo punto. Tuttavia, questa domanda è l'unica volta in cui ho mai visto questo problema menzionato. Mock supporta già spec-objects, quindi dovrebbe essere possibile? – jan

risposta

5

Archivia una richiesta di funzionalità per la simulazione.

problema fondamentale è che non hanno accesso alla funzione reale/classe finta non ha alcun modo di sapere l'ordine degli argomenti a parola chiave, che è invocazioni call(a=1, b=2) e call(b=2, a=1) sembrare identici a deridere, mentre invocazioni call(1, 2) e call(2, 1) non lo fanno.

Se si desidera generalizzare finta, è necessario passare un prototipo di chiamata o una funzione al posto di prototipo, per esempio:

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

Dal Python 3.4, proprio come volevi, affermando di specifiche firme di chiamata viene normalizzato automaticamente quando viene creato un Mock chiamabile con una specifica e per i metodi oggetto quando si utilizza la speculazione automatica.

Dalla fine del the documentation of the Mock class:

Un finto callable che è stato creato con una specifica (o uno spec_set) sarà introspezione firma dell'oggetto specifica in caso di corrispondenza chiamate verso il mock. Pertanto, si può abbinare l'argomento della chiamata effettiva indipendentemente dal fatto che siano passati posizionale o per nome:

>>> 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) 

Questo vale per assert_called_with(), assert_called_once_with(), assert_has_calls() e assert_any_call(). Quando esegui l'autospecing, lo stesso vale per le chiamate al metodo sull'oggetto fittizio, .

Modificato nella versione 3.4: Aggiunta dell'introspezione della firma su oggetti fittizi specifici e autospecced.

Problemi correlati