2016-01-22 17 views
6

Quando un oggetto unittest.mock.Mock è stato chiamato, posso controllare per i valori degli argomenti con la firma esatta della chiamata:controlla gli argomenti call unittest.mock agnosticamente w.r.t. se sono state passate come argomenti posizionali o argomenti chiave

from unittest.mock import Mock 

m = Mock() # creation of mock 
m('foo', bar='baz') # call to the mock 
m.assert_called_once_with('foo', bar='baz') # check call arguments 

Verifica di una firma diversa con la gli stessi valori falliranno. Per esempio, se controlliamo con 'baz' come argomento posizionale, invece di un argomento di nome, l'asserzione fallirà:

m.assert_called_once_with('foo', 'baz') 
# AssertionError: Expected call: mock('foo', 'baz') 
# Actual call: mock('foo', bar='baz') 

Deve. Se la funzione sostituito da m era

def actual_fu(foo, bar): 
    # do something 

poi le chiamate sarebbero equivalenti, ma se era

def a_different_actual_fu(foo, *args, bar='some default'): 
    # do something 

poi le chiamate non sarebbe equivalente. Mock non conosce la firma della funzione effettiva, quindi non può fare affidamento sull'equivalenza che avremmo nel primo caso.

Esiste un modo di controllare i valori degli argomenti di chiamata che è agnostica sul fatto che sono stati passati posizionale o come argomenti chiave, lasciando il Mock (o una funzione di affermazione di supporto o simile) conoscere circa la reale funzione sostituito da la finta?

L'oggetto Mock può essere consapevole dell'oggetto sostituisce (che può essere una funzione o metodo) opzionale spec argument o con autospeccing, ma quelli servire uno scopo diverso (limitare ciò chiama a consentire il finto) e non influisce sul controllo after-the-fact.

+1

per quanto ne so non è possibile farlo in finta 1.3. Ma ... IMHO non è un dovere finto cercare di capire la chiamata semantica ma solo registrare come si fa la chiamata. "assert_called_once_with (...)" è proprio quello che dice il metodo e non "assert_called_with_something_that_is_equivalent_to (...)": sembra più un dovere di stub. Comunque forse può essere molto utile in alcuni casi .... Ho incontrato qualcosa che è legato a questo alcuni giorni fa http://stackoverflow.com/a/34811786/4101725 –

risposta

3

L'oggetto fittizio può essere fatto consapevole dell'oggetto sostituisce (che può essere una funzione o metodo) con l'argomento spec opzionale o con autospeccing, ma quelli hanno uno scopo diverso ..

Questo è esattamente il problema di miglioramento di Issue 17015: mock could be smarter and inspect the spec's signature. Lo spec è in realtà molto correlato e ora rende mock function-signature-aware.

Vedere come finta fallisce quando affermiamo finto è stato chiamato con un argomento chiave - senza farla conoscere la firma effettiva funzione:

>>> from unittest.mock import Mock 
>>> 
>>> def actual_fu(foo, bar): 
...  pass 
>>> 
>>> m = Mock() 
>>> m('foo', bar='baz') 
<Mock name='mock()' id='4356741496'> 
>>> 
>>> m.assert_called_once_with(foo='foo', bar='baz') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/unittest/mock.py", line 803, in assert_called_once_with 
    return self.assert_called_with(*args, **kwargs) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/unittest/mock.py", line 792, in assert_called_with 
    raise AssertionError(_error_message()) from cause 
AssertionError: Expected call: mock(bar='baz', foo='foo') 
Actual call: mock('foo', bar='baz') 

E ora, vedere come il tutto passa se forniamo un spec:

>>> m = Mock(spec=actual_fu) 
>>> m('foo', bar='baz') 
<Mock name='mock()' id='4356249528'> 
>>> 
>>> m.assert_called_once_with(foo='foo', bar='baz') 
>>> m.assert_called_once_with('foo', bar='baz') 
>>> m.assert_called_once_with(bar='baz', foo='foo') 
>>> m.assert_called_once_with('foo', 'baz') 
>>> 

(Usato Python 3.5.1)

+0

Oh, wow. In realtà avevo provato qualcosa del genere, ma probabilmente con Python 3.2 dove non funzionava. Riprovato con Python 3.4 proprio ora e funziona! :-) –

Problemi correlati