在python上模拟超类调用

时间:2012-10-26 19:53:44

标签: python unit-testing mocking

我正在进行一些单元测试,在某些时候我需要模拟super调用以抛出错误,例如:

@classmethod
def myfunc(cls, *args, **kwargs)
    try:
        super(MyClass, cls).my_function(args, kwargs)
    except MyException as e:
        #...

我正在使用mocker库来模拟我的对象,但我还没有找到一种模拟它的方法。

6 个答案:

答案 0 :(得分:32)

使用mock库,我会做这样的事情。

在班级定义中:

from somelib import ASuperClass

class MyClass(ASuperClass):
    def my_cool_method(self):
        return super(MyClass, self).my_cool_method()

在您致电MyClass的模块中:

from mock import patch
from mymodule import MyClass

@patch("mypackage.mymodule.ASuperClass.my_cool_method")
def call_with_mock(mocked_super):
    myinstance = MyClass()
    myinstance.my_cool_method()
    # do stuff with `mocked_super`

call_with_mock()

更新:从Python 3.3开始,模拟库是unittest.mock下标准库的一部分。

答案 1 :(得分:7)

我找到了一种方式,有点hacky但它​​有效,我会用我的例子解释,这是基于this回复所以谢谢@kindall:

def my_test(self):
    import __builtin__
    from mocker import Mocker, KWARGS, ARGS

    mymocker = mocker.mock()
    mymocker.my_function(ARGS, KWARGS)
    mocker.throw(MyException)

    def mysuper(*args, **kwargs):
        if args and issubclass(MyClass, args[0]):
            return mymocker
        return original_super(*args, **kwargs)

    __builtin__.original_super = super
    __builtin__.super = mysuper

    with mocker:
        MyClass.myfunc()

基本上我所做的就是检查super调用是否来自我想要模拟的类,否则只需执行正常的super

希望这有助于某人:)

答案 2 :(得分:0)

那么你需要嘲笑my_function超类的MyClass方法才能爆炸。

答案 3 :(得分:0)

@Markus正在寻找合适的地方。只要您进行单元测试(即只有一次调用super),您就可以模仿__builtin__.super,如下所示:

with mock.patch('__builtin__.super') as mock_super:
    mock_super.side_effect = TypeError
    with self.assertRaises(TypeError):
        obj.call_with_super()

答案 4 :(得分:0)

万一有人需要另一种方法来解决此模拟问题:

# some_package/some_module.py

class MyClass(SuperClass):

    def some_function(self):
        result_super_call = super().function()

# test_file.py

@patch('some_package.some_module.super')
def test_something(self, mock_super):
    obj = MyClass()
    mock_super().some_function.return_value = None

    obj.authenticate()

使用Python 3.6

答案 5 :(得分:0)

Python自己的Mock类provides a spec argument应该会帮助您:

with mock.patch('...ParentClass.myfunc') as mocked_fn:
    mocked_fn.side_effect = MyException()  # Parent's method will raise
    instance = mock.Mock(spec=MyClass)  # Enables using super()
    MyClass.myfunc(instance)  # Will enter your `except` block