2012-02-19 4 views
6

Dopo aver letto questo: How do I mock an open used in a with statement (using the Mock framework in Python)?Python Mock - Mocking diversi aperto

io sono in grado di prendere in giro la funzione di apertura in Python utilizzando:

with patch(open_name, create=True) as mock_open: 
    mock_open.return_value = MagicMock(spec=file) 
    m_file = mock_open.return_value.__enter__.return_value 
    m_file.read.return_value = 'text1' 

    diffman = Diffman() 
    diffman.diff(path1, path2) 

funziona bene quando il mio metodo collaudato utilizzato una dichiarazione aperta. Qui è il mio metodo collaudato:

def diff(self, a, b): 
    with open(a, 'r') as old: 
     with open(b, 'r') as new: 
      oldtext = old.read() 
      newtext = new.read() 

I valori di oldtext e nuovoTesto sono gli stessi ('text1' qui).

Mi piacerebbe avere 'text1' per il vecchio testo e 'testo2' per il nuovo testo.

Come posso fare questo?

risposta

5

Ecco un modo rapido per ottenere ciò che desideri. Trucchi un po 'perché i due oggetti file nel metodo in prova sono lo stesso oggetto e stiamo solo cambiando il valore di ritorno della chiamata letta dopo ogni lettura. È possibile utilizzare la stessa tecnica in più livelli se si desidera che gli oggetti del file siano diversi, ma sarà piuttosto disordinato e potrebbe nascondere l'intento del test senza necessità.

Sostituire questa linea:

 
    m_file.read.return_value = 'text1' 

con:

 
    reads = ['text1', 'text2'] 
    m_file.read.side_effect = lambda: reads.pop(0) 
3

Forse una buona soluzione possibile è solo per scrivere il codice in un modo che meglio si presta alla sperimentazione facilmente. Nel caso di "diff", sembra abbastanza facile (non avendo molto altro contesto, bisogna ammetterlo) per avere diff come argomenti argomenti oggetti già aperti. Questo è probabilmente un cambiamento abbastanza piccolo da fare nel codice, e rende il test molto facile, dal momento che puoi facilmente fornire oggetti di file di simulazione a diff() quando lo provi, invece di cercare di saltare attraverso i cerchi che deridono due istanze dello stesso builtin funzione come un gestore di contesto chiamato all'interno ... stesso ... o qualcosa ;-)

import StringIO 

diff(a, b): 
    oldtext = a.read() 
    newtext = b.read() 

def test_diff(): 
    a = StringIO.StringIO('text1') 
    b = StringIO.StringIO('text2') 

    res = diff(a, b) 
    <some assertion here> 

Questo lavoro potrebbe funzionare?