Проверка Python, если метод вызывается без насмешки
class A():
def tmp(self):
print("hi")
def b(a):
a.tmp()
Чтобы проверить, вызван ли метод tmp в b, рекомендуется
a = A()
a.tmp = MagicMock()
b(a)
a.tmp.assert_called()
Но TMP здесь высмеивается и не приводит к "hi"
печатать.
Я хотел бы, чтобы мой модульный тест проверял, вызван ли метод tmp, без насмешек.
Это возможно?
Я знаю, что это не стандартная вещь, которую следует ожидать при написании юнитов. Но мой вариант использования (что немного сложнее) требует этого.
3 ответа
Вы можете установить Mock.side_effect
быть оригинальным методом.
from unittest.mock import MagicMock
class A():
def tmp(self):
print("hi")
def b(a):
a.tmp()
a = A()
a.tmp = MagicMock(side_effect=a.tmp)
b(a)
a.tmp.assert_called()
когда side_effect
является функцией (или связанным методом в данном случае, который является своего рода функцией), вызывая Mock
также назову side_effect
с теми же аргументами.
Mock()
Звонок вернется независимо от side_effect
возвращается, если он не возвращает unnittest.mock.DEFAULT
синглтон. Тогда он вернется Mock.return_value
вместо.
В дополнение к ответу @Patrick Haugh вы также можете передать функциюwraps
аргумент (и он кажется мне семантически более правильным).
wraps: элемент для обертывания фиктивного объекта. Если wraps не None, то вызов Mock передаст вызов завернутому объекту (возвращая реальный результат). Доступ к атрибуту на макете вернет объект Mock, который обертывает соответствующий атрибут обернутого объекта (поэтому попытка доступа к несуществующему атрибуту вызовет AttributeError).
a = A()
a.tmp = MagicMock(wraps=a.tmp)
b(a)
a.tmp.assert_called()
Или вы можете украсить метод для тестирования:
def check_called(fun):
def wrapper(self, *args, **kw):
attrname = "_{}_called".format(fun.__name__)
setattr(self, attrname, True)
return fun(self, *args, **kw)
return wrapper
a = A()
a.tmp = check_called(a.tmp)
b(a)
assert(getattr(a, "_tmp_called", False))
но MagicMock's side_effect
это определенно лучшее решение, если вы уже используете Mock;)