Слід зазначити, що кілька відповідей тут будуть виправляти декоратор протягом усього тестового сеансу, а не окремий екземпляр тесту; що може бути небажаним. Ось як виправити декоратор, який зберігається лише під час одного тесту.
Наш пристрій, який буде протестовано з небажаним декоратором:
from app.decorators import func_decor
@func_decor
def unit_to_be_tested():
pass
З модуля декораторів:
def func_decor(func):
def inner(*args, **kwargs):
print "Do stuff we don't want in our test"
return func(*args, **kwargs)
return inner
На той час, коли наш тест збирається під час пробного запуску, небажаний декоратор вже був застосований до нашого випробовуваного блоку (оскільки це відбувається під час імпорту). Щоб позбутися цього, нам доведеться вручну замінити декоратор в модулі декоратора, а потім повторно імпортувати модуль, що містить наш UUT.
Наш тестовий модуль:
from unittest import TestCase
from app import uut
from app import decorators
import imp
from mock import patch
class TestUUT(TestCase):
def setUp(self):
def kill_patches():
patch.stopall()
imp.reload(uut)
self.addCleanup(kill_patches)
patch('app.decorators.func_decor', lambda x: x).start()
imp.reload(uut)
Зворотний виклик очищення, kill_patches, відновлює оригінальний декоратор і повторно застосовує його до блоку, який ми тестували. Таким чином, наш патч зберігається лише під час одного тесту, а не всього сеансу - саме так повинен поводитися будь-який інший патч. Крім того, оскільки очищення викликає patch.stopall (), ми можемо запустити будь-які інші потрібні нам патчі, і вони будуть очищені в одному місці.
Головне, що слід зрозуміти при цьому методі, - це те, як перезавантаження вплине на речі. Якщо модуль займає занадто багато часу або логіка працює під час імпорту, можливо, вам просто доведеться знизати плечима та протестувати декоратор як частину блоку. :( Сподіваємось, ваш код написаний краще, ніж це. Так?
Якщо вам байдуже, застосовується патч до всього тестового сеансу , найпростіший спосіб це зробити - у верхній частині тестового файлу:
from mock import patch
patch('app.decorators.func_decor', lambda x: x).start()
from app import uut
Переконайтесь, що виправляєте файл за допомогою декоратора, а не локальної області UUT, і запускаєте виправлення перед імпортом блоку за допомогою декоратора.
Цікаво, що навіть якщо патч зупинено, усі файли, які вже імпортували, все одно матимуть патч до декоратора, що є зворотною ситуацією, з якої ми почали. Майте на увазі, що цей метод буде виправляти будь-які інші файли в тестовому запуску, які імпортуються згодом - навіть якщо вони не оголошують виправлення самостійно.