2013-04-23 18 views
62

Per il momento abbiamo utilizzato Mock per python.Funzione Python di simulazione basata su argomenti di input

Ora, abbiamo una situazione in cui si vuole deridere una funzione

def foo(self, my_param): 
    #do something here, assign something to my_result 
    return my_result 

Normalmente, il modo per deridere questo sarebbe (supponendo foo essendo parte di un oggetto)

self.foo = MagicMock(return_value="mocked!") 

Anche se chiamo foo() un paio di volte posso usare

self.foo = MagicMock(side_effect=["mocked once", "mocked twice!"]) 

Ora, sto affrontando una situazione in cui io desidera restituire un valore fisso quando il parametro di input ha un valore particolare. Quindi, se diciamo "my_param" è uguale a "qualcosa" allora voglio tornare "my_cool_mock"

Questo sembra essere disponibile su mockito for python

when(dummy).foo("something").thenReturn("my_cool_mock") 

Sono stato alla ricerca su come ottenere lo stesso con Mock senza successo?

Qualche idea?

+2

Potrebbe essere questa risposta aiuterà - http://stackoverflow.com/a/7665754/234606 – naiquevin

+0

@naiquevin Questo risolve perfettamente il problema amico, grazie! –

+0

Non avevo idea che potessi usare Mocktio con Python, +1 per quello! – Ben

risposta

85

Se side_effect è una funzione, allora tutto ciò che è funzione restituisce quello che chiama al ritorno finta. La funzione side_effect viene chiamata con gli stessi argomenti della simulazione. Ciò consente di variare il valore di ritorno della chiamata in modo dinamico, in base ai contributi:

>>> def side_effect(value): 
...  return value + 1 
... 
>>> m = MagicMock(side_effect=side_effect) 
>>> m(1) 
2 
>>> m(2) 
3 
>>> m.mock_calls 
[call(1), call(2)] 

http://www.voidspace.org.uk/python/mock/mock.html#calling

+7

Per semplificare la risposta, potresti rinominare la funzione side_effect in qualcos'altro? (lo so, lo so, è piuttosto semplice, ma migliora la leggibilità il fatto che il nome della funzione e il nome del param sono diversi :) –

+4

@JuanAntonioGomezMoriano Potrei, ma in questo caso sto solo citando direttamente la documentazione, quindi sono un po 'detestare modificare la citazione se non è specificamente rotto. – Amber

+0

e solo per essere pedante tutti questi anni più tardi, ma "effetto collaterale" è il termine preciso: https://en.wikipedia.org/wiki/Side_effect_(computer_science) – lsh

12

Come indicato al Python Mock object with method called multiple times

Una soluzione è quella di scrivere il mio side_effect

def my_side_effect(*args, **kwargs): 
    if args[0] == 42: 
     return "Called with 42" 
    elif args[0] == 43: 
     return "Called with 43" 
    elif kwarg['foo'] == 7: 
     return "Foo is seven" 

mockobj.mockmethod.side_effect = my_side_effect 

Questo fa il trucco

5

Effetto collaterale prende una funzione (che può anche essere una funzione lambda), quindi per i casi semplici è possibile utilizzare:

m = MagicMock(side_effect=(lambda x: x+1)) 
0

Solo per mostrare un altro modo di farlo:

def mock_isdir(path): 
    return path in ['/var/log', '/var/log/apache2', '/var/log/tomcat'] 

with mock.patch('os.path.isdir') as os_path_isdir: 
    os_path_isdir.side_effect = mock_isdir 
Problemi correlati