【问题标题】:proper way python mock __init__() method that returns a fake class返回假类的正确方式python模拟__init__()方法
【发布时间】:2012-03-12 15:34:36
【问题描述】:

试图模拟对 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

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

【问题讨论】:

    标签: python unit-testing mocking


    【解决方案1】:

    您似乎对__init__() 的作用有误解。它的目的是初始化一个之前已经创建的实例。 __init__()的第一个参数是self,也就是实例,所以在调用__init__()的时候可以看到它已经被分配了。

    有一个方法__new__()__init__() 之前调用以创建实际实例。不过,我认为将整个类替换为模拟类而不是模拟单个方法会容易得多。

    【讨论】:

    • 感谢您的指点。我知道替换 init 返回的对象感觉不对,但是在模拟文档中我找不到他们模拟实际类的地方。类方法,是的,但不是类本身。这现在看起来很明显,但不是一个小时前:-)。 @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')
    猜你喜欢
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多