Я пытаюсь выполнить unittest класс, который имеет довольно сложный __init__, включающий вызовы серверов и внешних компонентов. Я обнаружил, что вы можете использовать unittest MagicMock для подделки init.
class my_class:
def __init__(self, arg1, arg2):
self.var = arg1
self.method1(arg2)
def method1(self, arg):
var = "Hello " + arg
self.method2(var)
def method2(self, var):
print(var)
SELF = MagicMock()
my_calss.my_class.__init__(SELF, arg1, arg2)
Это здорово, потому что весь код, который общается с сервером, находится в других методах, и я могу убедиться, что __init__ вызывает определенные методы.
Проблема возникает, когда я хочу протестировать метод, который вызывает другой метод.
SELF = MagicMock()
my_class.__init__(SELF, arg1, arg2)
SELF.method2 = my_class.method2
my_class.method1(SELF, arg)
Я бы ожидал, что self в method2 будет SELF, но method2 никогда не получит self. Есть ли способ гарантировать, что method2 получит поддельный SELF?
Или другой метод тестирования методов класса, не требующий множества патчей?






Я не думаю, что вы сможете добиться этого с MagicMock.
Один из подходов - использовать метод класса __new__ для создания экземпляра вашего класса без вызова его метода __init__, а затем настроить его свойства в настройках теста по мере необходимости.
Например
instance = my_class.__new__(my_class)
# Manually initialize properties as needed.
instance.usually_set_by_init = 3
# Use the instance like normal.
instance.method1(arg)
Если вы не слышали о __new__, это может показаться странным, но полезно понимать, что a = A() эквивалентен a = A.__new__(A); a.__init__().
Вы могли бы, но вышеупомянутый подход вызовет значительно меньше головной боли.
Вы можете просто заглушить класс вместо насмешек.
class MyClassStub(MyClass):
def __init__(self):
pass # bypass parents init
Итак, нет возможности добавить методы к объекту Mock?