2012-03-12 13 views
5

Próbujesz wyśmiewać połączenia z biblioteką pyazure do testowania django, ale nie mogę wymyślić, jak wyćwiczyć konstruktor klasy PyAzure, aby nie powodował a TypeError. Czy istnieje lepszy sposób podejścia do kpienia z biblioteki dostępu, która generuje obiekt połączenia?Właściwy sposób python mock __init __() metoda, która zwraca fałszywą klasę

Wszystko, co próbowałem poza None, generuje TypeError, co oznacza, że ​​nie mogę nawet zacząć testować żadnej z metod połączeń PyAzure z rzeczywistymi wartościami zwracanymi. Jaki jest najlepszy sposób na zastąpienie klasy robotniczej fałszywą klasą za pomocą makiety?

test Błąd:

====================================================================== 
ERROR: test_management_certificate_connect (azure_cloud.tests.ViewsTest) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/Users/bschott/Source/django-nimbis/apps/azure_cloud/tests.py", line 107, in test_management_certificate_connect 
self.cert1.connect() 
File "/Users/bschott/Source/django-nimbis/apps/azure_cloud/models.py", line 242, in connect 
    subscription_id=self.subscription.subscription_id) 
TypeError: __init__() should return None, not 'FakeAzure' 
---------------------------------------------------------------------- 

tests.py:

class ViewsTest(TestCase): 
    def setUp(self): 
    ... 
     self.cert1 = ManagementCertificate.objects.create(
      name="cert1", 
      subscription=self.subscription1, 
      management_cert=File(open(__file__), "cert1.pem"), 
      owner=self.user1) 
    ... 

    class FakeAzure(object): 
     """ testing class for azure """ 
     def list_services(self): 
      return ['service1', 'service2', 'service3'] 
     def list_storages(self): 
      return ['storage1', 'storage2', 'storage3'] 

    @mock.patch.object(pyazure.PyAzure, '__init__') 
    def test_management_certificate_connect(self, mock_pyazure_init): 
     mock_pyazure_init.return_value = self.FakeAzure() 
     self.cert1.connect() 
     assert mock_pyazure_init.called 

models.py

class ManagementCertificate(models.Model): 

    # support connection caching to azure 
    _cached_connection = None 

    def connect(self): 
     """ 
     Connect to the management interface using these credentials. 
     """ 
     if not self._cached_connection: 
      self._cached_connection = pyazure.PyAzure(
       management_cert_path=self.management_cert.path, 
       subscription_id=self.subscription.subscription_id) 
      logging.debug(self._cached_connection) 
     return self._cached_connection 

Odpowiedz

11

Wydaje się, mają błędne przekonanie o tym, co __init__() robi. Jego celem jest zainicjowanie instancji, która została wcześniej utworzona. Pierwszy argument do __init__() to self, który jest instancją, więc można zobaczyć, że został już przydzielony po wywołaniu __init__().

Istnieje metoda __new__(), która jest wywoływana przed __init__(), aby utworzyć rzeczywistą instancję. Myślę, że znacznie łatwiej byłoby zastąpić całą klasę fałszywą klasą zamiast kpić z pojedynczych metod.

+2

+1 Zamiast tego kpisz z klasy. –

+0

Dzięki za wskazówki. Wiedziałem, że zastąpienie obiektu zwróconego przez __init__ po prostu źle się sprawdziło, ale nigdzie w fałszywych dokumentach nie znalazłem miejsca, w którym kpią z rzeczywistych klas. Metody klas, tak, ale nie same klasy. To teraz wydaje się oczywiste, ale nie było godziny temu :-). @ mock.patch.object (pyazure 'PyAzure' Spec = pyazure.PyAzure) def test_management_certificate_connect (samodzielne mock_pyazure) self.cert1.connect() mock_pyazure.assert_called_with ('foo' 'bar') – bfschott

Powiązane problemy