Is it possible to mock a python constructor while continuing to use the production version other fields/functions on the same name? For example, given the production code:
class MyClass:
class SubClass:
def __init__(self) -> None:
print("\nreal sub init called")
class SubSubClass:
def __init__(self) -> None:
print("\nreal sub sub init called")
and the following test code:
class FakeSubClass:
def __init__(self) -> None:
print("\nfake init called")
def test():
MyClass.SubClass()
MyClass.SubClass.SubSubClass()
MyClass.SubClass = Mock(side_effect=FakeSubClass)
MyClass.SubClass()
MyClass.SubClass.SubSubClass()
we get the following output:
real sub init called
real sub sub init called
fake init called
Note that the last line MyClass.SubClass.SubSubClass()
did not create a real SubSubClass because at this point it is an automatically created property of the SubClass mock.
My desired output is the following:
real sub init called
real sub sub init called
fake init called
real sub sub init called
In other words I want to mock ONLY the SubClass, but not SubSubClass. Things I have tried in place of the mocking line above (both of which do not work):
MyClass.SubClass.__init__ = Mock(side_effect=FakeSubClass.__init__)
MyClass.SubClass.__new__ = Mock(side_effect=FakeSubClass.__new__)
Note that I am aware of several ways the code could be refactored to avoid this issue but sadly the code cannot be refactored.