Можно ли издеваться над конструктором python, продолжая использовать производственную версию других полей / функций с тем же именем? Например, с учетом производственного кода:
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")
и следующий код теста:
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()
получаем следующий вывод:
real sub init called
real sub sub init called
fake init called
Обратите внимание, что последняя строка MyClass.SubClass.SubSubClass()
не создала настоящий SubSubClass, потому что на данный момент это автоматически созданное свойство макета SubClass.
Мой желаемый вывод следующий:
real sub init called
real sub sub init called
fake init called
real sub sub init called
Другими словами, я хочу высмеивать ТОЛЬКО подкласс, но не подкласс. Вещи, которые я пробовал вместо насмешливой строки выше (оба из которых не работают):
MyClass.SubClass.__init__ = Mock(side_effect=FakeSubClass.__init__)
MyClass.SubClass.__new__ = Mock(side_effect=FakeSubClass.__new__)
Обратите внимание, что мне известно о нескольких способах рефакторинга кода, чтобы избежать этой проблемы, но, к сожалению, код не может быть реорганизован.