2012-05-25 3 views
20

OK,
So che questo è menzionato nel manual e probabilmente ha a che fare con side_effect e/o return_value, ma un semplice esempio diretto mi aiuterà immensamente.Come si simula una classe Python e si ottiene un nuovo oggetto Mock per ogni istanza?

ho:

class ClassToPatch(): 
    def __init__(self, *args): 
     _do_some_init_stuff() 

    def some_func(): 
     _do_stuff() 


class UUT(): 
    def __init__(self, *args) 
     resource_1 = ClassToPatch() 
     resource_2 = ClassToPatch() 

Ora, voglio test di unità della classe UUT, e deridere il ClassToPatch. Conoscendo la classe UUT sarà istanziare esattamente due ClassToPatch oggetti, voglio che il quadro Mock per restituire un nuovo oggetto Mock per ogni esemplificazione, in modo da poter poi far valere le chiamate su ogni separatamente.

Come faccio a ottenere questo utilizzando il @patch decoratore in un banco di prova? Vale a dire, come risolvere il seguente esempio di codice?

class TestCase1(unittest.TestCase): 

    @patch('classToPatch.ClassToPatch',autospec=True) 
    def test_1(self,mock1,mock2): 
     _assert_stuff() 

risposta

21

Ecco un esempio quick'n'dirty per farti andare:

import mock 
import unittest 

class ClassToPatch(): 
    def __init__(self, *args): 
     pass 

    def some_func(self): 
     return id(self) 

class UUT(): 
    def __init__(self, *args): 
     resource_1 = ClassToPatch() 
     resource_2 = ClassToPatch() 
     self.test_property = (resource_1.some_func(), resource_2.some_func()) 

class TestCase1(unittest.TestCase): 
    @mock.patch('__main__.ClassToPatch', autospec = True) 
    def test_1(self, mock1): 
     ctpMocks = [mock.Mock(), mock.Mock()] 
     ctpMocks[0].some_func.return_value = "funky" 
     ctpMocks[1].some_func.return_value = "monkey" 
     mock1.side_effect = ctpMocks 

     u = UUT() 
     self.assertEqual(u.test_property, ("funky", "monkey")) 

if __name__ == '__main__': 
    unittest.main() 

Ho aggiunto test_property a UUT in modo che il test di unità fa qualcosa di utile. Ora, senza il simulato, test_property dovrebbe essere una tupla contenente gli ID delle due istanze ClassToPatch. Ma con la finta dovrebbe essere la tupla: ("funky", "monkey").

Ho utilizzato la proprietà side_effect dell'oggetto fittizio in modo che venga restituita una diversa istanza di ClassToPatch per ogni chiamata nell'inizializzatore UUT.

Spero che questo aiuti.

Edit: Oh, a proposito, quando si esegue il test di unità ottengo:

. 
---------------------------------------------------------------------- 
Ran 1 test in 0.004s 

OK 
+0

(Nuovo per Python :) Un modo per modificare questo di lavorare sotto Python 2.7? –

+0

Ho appena eseguito questo codice in Python 2.7.9 (win32) e ha funzionato correttamente. Che errore stai ottenendo? – srgerg

+0

~ $ python --version Python 2.7.5 AttributeError: non ha l'attributo 'ClassToPatch' –