Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I mock/patch a decorator in python?

WORKAROUND:

I was unable to patch the decorator and still have access to the wrapped function. but the workaround for me to test the function wrapped in a decorator was the following:

def un_some_method(self):
...

some_method = some_var.some_decorator('somestring')(un_some_method)    

This still decorates my function, but gives me access to the function if I wish to test it, reuse it elsewhere...

This is the problem:

I have a module, which has a class in it, and variables that instantiate a class which expose a decorator.

Then within the class inside my module, I use this variable with the instance of my class and decorate a method in my class... To be clear, lets look at some code:

some_var = ClassX()

class SomeClass(object):

    @some_var.some_decorator('somestring')
    def some_method(self):
        ...

in my test I want to test the code within some_method and I don't care about the decorator... although my attempts to mock the decorator out was useless... below is some things I tried:

@patch('path_to_classx.ClassX.some_decorator')
@patch('path_to_someclassmodule.some_var')
@patch('path_to_someclassmodule.ClassX')

none of the attempts above prevented the function from being decorated... any idea why?

like image 745
Pippo Avatar asked Dec 09 '15 14:12

Pippo


1 Answers

One option is to patch some_var after you have instantiated it, replacing some_decorator with an identity function so that the decorated method remains unchanged.

import mock
class ClassX(object):
    def some_decorator(self, f):
        def g(*args, **kwargs):
            print("Hello")
            return f(*args, **kwargs)
        return g

some_var = ClassX()

with mock.patch.object(some_var, 'some_decorator', side_effect=lambda f: f):

    class SomeClass(object):
        @some_var.some_decorator
        def some_method(self):
            print "World"


SomeClass().some_method()
like image 117
chepner Avatar answered Nov 15 '22 00:11

chepner