简体   繁体   English

正确的方法python mock __init __()方法返回一个假类

[英]proper way python mock __init__() method that returns a fake class

Trying to mock out calls to pyazure library for django testing, but I can't figure out how to mock out the PyAzure class constructor so that it doesn't cause a TypeError. 试图模拟调用pyazure库进行django测试,但我无法弄清楚如何模拟PyAzure类构造函数,以便它不会导致TypeError。 Is there a better way to approach mocking out an access library that generates a connection object? 有没有更好的方法来模拟生成连接对象的访问库?

Anything I've tried other than None generates a TypeError, which means I can't really even begin to test any of the PyAzure connection methods with actual return values. 我尝试过的除None之外的任何东西都会产生TypeError,这意味着我甚至无法开始使用实际返回值来测试任何PyAzure连接方法。 What is the best way to replace a working class with a fake class using mock? 使用mock替换假类的最佳方法是什么?

Test 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: 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 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

You seem to have a misconception about what __init__() does. 您似乎对__init__()含义存在误解。 Its purpose is to initialise an instance that was already created earlier. 其目的是初始化先前已创建的实例。 The first argument to __init__() is self , which is the instance, so you can see it was already allocated when __init__() is called. __init__()的第一个参数是self ,它是实例,因此您可以看到在调用__init__()时已经分配了它。

There is a method __new__() that is called before __init__() to create the actual instance. __init__()之前调用了一个方法__new__() __init__()来创建实际的实例。 I think it would be much easier, though, to replace the whole class by a mock class, instead of mocking single methods. 但是,我认为用模拟类替换整个类会更容易,而不是模仿单个方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM