Как издеваться над украшенной функцией

По причинам тестирования мне нужно уметь издеваться над внутренней/оригинальной функцией украшенной, которая используется где-то еще:

В mydecorator.py:

def my_decorator(f):
    def wrapped_f():
        print "decorated"
        f()
    return wrapped_f


@my_decorator
def function_to_be_mocked():
    print 'original'


def function_to_be_mocked_undecorated():
    print 'original'


def run_decorated():
    function_to_be_mocked()


def run_undecorated():
    decorated_funtion = my_decorator(function_to_be_mocked_undecorated)
    decorated_funtion()

Как вы можете видеть, у меня есть несколько версий исходной функции function_to_be_mocked, одна с декоратором my_decorator и одна "голой". Функция runner run_decorated() вызывает декорированную версию функции function_to_be_mocked, а run_undecorated() вызывает неподтвержденную версию и применяет декоратор "вручную". Результат обоих одинаков:

decorated
original

Теперь я хочу протестировать функцию runner, но мне нужно высмеять исходную функцию function_to_be_mocked, но также должна быть украшена издеваемая версия:

import unittest
import mydecorator
from mock import patch

def mock_function():
    print 'mockified'

class Test(unittest.TestCase):

    @patch('mydecorator.function_to_be_mocked_undecorated')
    def test_undecorated_mocked(self, mock_function_to_be_mocked_undecorated):
        mydecorator.function_to_be_mocked_undecorated = mock_function
        mydecorator.run_undecorated()
        assert 1==0

    @patch('mydecorator.function_to_be_mocked')
    def test_decoratorated_mocked(self, mock_function_to_be_mocked):
        mydecorator.function_to_be_mocked = mock_function
        mydecorator.run_decorated()
        assert 1==0

Это работает, как и ожидалось, для недекорированной версии test_undecorated_mocked:

decorated
mockified

Но оформленная версия дает:

mockified

поэтому декоратор исчез.

Возможно ли, чтобы оформленная версия работала так же, как и декодированная версия, где декоратор применяется "вручную"?

Я попытался разоблачить внутреннюю функцию в декораторе без успеха.

Я видел этот вопрос Как вы издеваетесь над функцией, которую декоратор применяет к ней в unit test?, но это мне не помогает.

Ответ 1

Python применяет декоратор при загрузке модуля, поэтому установка function_to_be_mocked в mock_function в test_decoratorated_mocked действительно изменит эту функцию на неупорядоченную функцию.

Вам нужно будет вручную добавить декоратор снова, если вы хотите издеваться над function_to_be_mocked:

mydecorator.function_to_be_mocked = mydecorator.my_decorator(mock_function)