правильный способ Python mock __init __ () метод, который возвращает поддельный класс - PullRequest
5 голосов
/ 12 марта 2012

Попытка смоделировать вызовы библиотеки Pyazure для тестирования django, но я не могу понять, как смоделировать конструктор класса PyAzure, чтобы он не вызывал TypeError.Есть ли лучший способ подойти к моделированию библиотеки доступа, которая генерирует объект соединения?

Все, что я пробовал, кроме None, генерирует ошибку TypeError, что означает, что я не могу даже начать тестировать любой изМетоды подключения PyAzure с фактическими возвращаемыми значениями.Каков наилучший способ заменить рабочий класс поддельным классом с помощью mock?

Ошибка теста:

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

модели.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

1 Ответ

11 голосов
/ 12 марта 2012

У вас, похоже, неправильное представление о том, что делает __init__(). Его цель - инициализировать экземпляр, который уже был создан ранее. Первый аргумент __init__() - это self, который является экземпляром, поэтому вы можете видеть, что он уже был выделен при вызове __init__().

Существует метод __new__(), который вызывается перед __init__() для создания фактического экземпляра. Я думаю, что было бы намного проще заменить целый класс фиктивным классом, вместо того, чтобы насмехаться над одиночными методами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...