简体   繁体   中英

Mocking the super class calls on python

I am doing some unit testing and at some point I need to mock a super call to throw an error, for example:

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

I am using the mocker library to mock my objects in general but I haven't found a way to mock this.

Using unittest.mock from the standard library I would do something like this.

In your class definition:

from somelib import ASuperClass

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

In the module where you are calling MyClass :

from unittest.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()

I found a way, sort of hacky but it works, I'll explain with my example, this is based on this response so thanks @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()

so essentially what I do is check if the super call is from the class I want to mock, else just do a normal super .

Hope this helps someone :)

In case anyone needs another way to solve this mock:

# 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

Using Python 3.6

@Markus is looking in the right place. So long as you're unit testing (ie there's only one call to super ), you can mock __builtin__.super as in:

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

Python's own Mock class provides a spec argument that should help with that:

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

好吧,那你就需要mock一下MyClass的超类的my_function方法来炸了。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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