I have a class with an expensive __init__ function. I don't want this function called from tests.
For the purpose of this example, I made a class that raises an Exception in __init__:
class ClassWithComplexInit(object):
    def __init__(self):
        raise Exception("COMPLEX!")
    def get_value(self):
        return 'My value'
I have a second class that constructs an instance of ClassWithComplexInit and uses it's function.
class SystemUnderTest(object):
    def my_func(self):
        foo = ClassWithComplexInit()
        return foo.get_value()
I am trying to write some unit tests around SystemUnderTest#my_func(). The problem I am having is no matter how I try to mock ClassWithComplexInit, the __init__ function always gets executed and the exception is raised.
class TestCaseWithoutSetUp(unittest.TestCase):
    @mock.patch('mypackage.ClassWithComplexInit.get_value', return_value='test value')
    def test_with_patched_function(self, mockFunction):
        sut = SystemUnderTest()
        result = sut.my_func()  # fails, executes ClassWithComplexInit.__init__()
        self.assertEqual('test value', result)
    @mock.patch('mypackage.ClassWithComplexInit')
    def test_with_patched_class(self, mockClass):
        mockClass.get_value.return_value = 'test value'
        sut = SystemUnderTest()
        result = sut.my_func()  # seems to not execute ClassWithComplexInit.__init__()
        self.assertEqual('test value', result)  # still fails
        # AssertionError: 'test value' != <MagicMock name='ClassWithComplexInit().get_value()' id='4436402576'>
The second approach above is one that I got from this similar Q&A but it didn't work either. It seemed to not run the __init__ function but my assertion fails because the result ends up being a mock instance as opposed to my value.
I also tried to configure a patch instance in the setUp function, using the start and stop functions as the docs suggest.
class TestCaseWithSetUp(unittest.TestCase):
    def setUp(self):
        self.mockClass = mock.MagicMock()
        self.mockClass.get_value.return_value = 'test value'
        patcher = mock.patch('mypackage.ClassWithComplexInit', self.mockClass)
        patcher.start()
        self.addCleanup(patcher.stop)
    def test_my_func(self):
        sut = SystemUnderTest()
        result = sut.my_func()  # seems to not execute ClassWithComplexInit.__init__()
        self.assertEqual('test value', result)  # still fails
        # AssertionError: 'test value' != <MagicMock name='mock().get_value()' id='4554658128'>
This also seems to avoid my __init__ function but the value I set for get_value.return_value isn't being respected and get_value() is still returning a MagicMock instance.
How can I mock a class with an complicated __init__ which is instantiated by my code under test? Ideally, I would like a solution which works well for many unit tests within a TestCase class (e.g. Not needing to patch every test).
I am using Python version 2.7.6.
First, you need to use the same name you are patching to create foo, that is,
class SystemUnderTest(object):
    def my_func(self):
        foo = mypackage.ClassWithComplexInit()
        return foo.get_value()
Second, you need to configure the correct mock object. You are configuring ClassWithComplexInit.get_value, the unbound method, but you need to configure ClassWithComplexInit.return_value.get_value, which is the Mock object that will be actually be called with foo.get_value().
@mock.patch('mypackage.ClassWithComplexInit')
def test_with_patched_class(self, mockClass):
    mockClass.return_value.get_value.return_value = 'test value'
    sut = SystemUnderTest()
    result = sut.my_func()  # seems to not execute ClassWithComplexInit.__init__()
    self.assertEqual('test value', result)  # still fails
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With