Я пишу несколько тестов, используя pytest с приспособлением monkeypatch. Следуя правилам, я импортирую классы и методы для имитации из модуля, в котором они используются, а не из источника.
Приложение, для которого я пишу тесты, представляет собой приложение Google App Engine, использующее стандартную среду. Таким образом, я должен использовать python 2.7, фактическая версия, которую я использую, — 2.7.15, а версия pytest — 3.5.0.
До сих пор все работало хорошо, но я столкнулся с проблемой при попытке смоделировать функцию декоратора.
Начиная сверху. В файле py с именем decorators.py содержатся все декораторы авторизации, включая декоратор, который я хочу смоделировать. Рассматриваемый декоратор является функцией модуля, а не частью класса.
def user_login_required(handler):
def is_authenticated(self, *args, **kwargs):
u = self.auth.get_user_by_session()
if u.access == '' or u.access is None:
# return the response
self.redirect('/admin', permanent=True)
else:
return handler(self, *args, **kwargs)
return is_authenticated
Декоратор применяется к функции веб-запроса. Простой пример в файле с именем UserDetails.py в папке с именем обработчики (handlers.UserDetails)
from decorators import user_login_required
class UserDetailsHandler(BaseHandler):
@user_login_required
def get(self):
# Do web stuff, return html, etc
В тестовом модуле я настраиваю тест следующим образом:
from handlers.UserDetails import user_login_required
@pytest.mark.parametrize('params', get_params, ids=get_ids)
def test_post(self, params, monkeypatch):
monkeypatch.setattr(user_login_required, mock_user_login_required_func)
Проблема в том, что monkeypatch не позволяет мне указать одну функцию в качестве цели. Он хочет, чтобы целью был класс, за которым следует имя метода, которое должно быть заменено, а затем фиктивный метод....
monkeypatch.setattr(WouldBeClass, "user_login_required", mock_user_login_required_func)
Я попытался настроить код, чтобы увидеть, смогу ли я обойти его, изменив способ импорта и использования декоратора следующим образом:
import decorators
class UserDetailsHandler(BaseHandler):
@decorators.user_login_required
def get(self):
# Do web stuff, return html, etc
Затем в тесте я пытаюсь исправить имя функции вот так.....
from handlers.UserDetails import decorators
@pytest.mark.parametrize('params', get_params, ids=get_ids)
def test_post(self, params, monkeypatch):
monkeypatch.setattr(decorators, "user_login_required" , mock_user_login_required_func)
Хотя этот код не выдает никаких ошибок, когда я прохожу тест, код никогда не входит в mock_user_login_required_func. Он всегда входит в живой декоратор.
Что я делаю неправильно? Это проблема с попыткой патчить декораторы в целом, или отдельные функции в модулях не могут быть исправлены?