mock __init__(self, ...): TypeError: super(type, obj): obj 必须是 type 的实例或子类

2 投票
1 回答
1790 浏览
提问于 2025-04-18 11:44

我试着像这样模拟一个类的构造函数,具体可以参考这个链接 https://stackoverflow.com/a/17950141/633961

class MockedHttpResponse(django.http.response.HttpResponseBase):
    def check(self, *args, **kwargs):
        status=kwargs.get('status')
        if status is None and self.status_code==200:
            return # default 
        if not status==self.status_code:
            raise self.AssertionErrorStatusCode('%s!=%s' % (self.status_code, status))

    def __init__(self, *args, **kwargs):
        self.check(*args, **kwargs)
        django.http.response.HttpResponseBase.__init__(self, *args, **kwargs)

    class AssertionErrorStatusCode(AssertionError):
        pass

在测试中的使用:

def test_assert_http_response_status__with_self_mocking(self):
    from django.http import HttpResponse
    with mock.patch('django.http.response.HttpResponse', testutils.MockedHttpResponse):
        HttpResponse(status=200)

但是我遇到了这个异常:

Traceback (most recent call last):
  File "/home/foo_eins_di514/src/djangotools/djangotools/tests/unit/utils/test_testutils.py", line 129, in test_assert_http_response_status__with_self_mocking
    HttpResponse(status=200)
  File "/home/foo_eins_di514/lib/python2.7/site-packages/django/http/response.py", line 258, in __init__
    super(HttpResponse, self).__init__(*args, **kwargs)
TypeError: super(type, obj): obj must be an instance or subtype of type

我该如何模拟一个类并修改它的 __init__() 方法呢?

1 个回答

0

我不是专家,所以不能确定 mock 是怎么工作的,但我可以告诉你一些基本情况。你可能在测试模块里把原来的 django.http.HttpResponse 对象固定住了,也就是说你在这里写了 from django.http import HttpResponse。如果 mock 没有在上下文管理器里动态修改 locals()globals() 来覆盖你引用的目标,那么对模块本身的任何修改都不会影响你在测试中使用的 HttpResponse 对象。至少你需要做的一步是,在 patch 的上下文管理器里明确引用这个类,虽然你也可以用 with mock.patch('django.http.response.HttpResponse', testutils.MockedHttpResponse) as HttpResponse: 这样来达到你想要的效果。我觉得你可能还想在 patch 中使用 new_callable=testutils.MockedHttpResponse 作为一个关键字参数。

撰写回答