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