2012-03-12 13 views
5

Intentando simular llamadas a la biblioteca pyazure para las pruebas de django, pero no puedo encontrar la manera de simular el constructor de la clase PyAzure para que no cause un TypeError. ¿Hay una mejor manera de abordar el burlarse de una biblioteca de acceso que genera un objeto de conexión?modo apropiado método __init __() que devuelve una clase falsa

Cualquier cosa que haya probado que no sea None genera un TypeError, lo que significa que realmente no puedo comenzar a probar ninguno de los métodos de conexión de PyAzure con valores de retorno reales. ¿Cuál es la mejor manera de reemplazar una clase trabajadora con una clase falsa usando simulacro?

prueba de error:

====================================================================== 
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 

Respuesta

11

Parece tener una idea equivocada acerca de lo que hace __init__(). Su propósito es inicializar una instancia que ya se creó anteriormente. El primer argumento para __init__() es self, que es la instancia, por lo que puede ver que ya se asignó cuando se llama al __init__().

Hay un método __new__() que se llama antes de __init__() para crear la instancia real. Creo que sería mucho más fácil, sin embargo, reemplazar a toda la clase por una clase falsa, en lugar de burlar solo los métodos.

+2

+1 Simula la clase en su lugar. –

+0

Gracias por los consejos. Sabía que reemplazar el objeto devuelto por __init__ simplemente me hacía sentir mal, pero en ninguna parte de los documentos falsos podría encontrar dónde se burlan de las clases reales. Métodos de clase, sí, pero no clases en sí. Esto ahora parece obvio, pero no hace una hora :-). @ mock.patch.object (pyazure, 'PyAzure', spec = pyazure.PyAzure) def test_management_certificate_connect (self, mock_pyazure): self.cert1.connect() mock_pyazure.assert_called_with ('foo', 'bar') – bfschott

Cuestiones relacionadas