Monkey patch a python function - issue

476 views Asked by At

I'm in trouble replacing a python function from a different module with a TestClass

I'm trying to test a part of my code that contains the function in a module; more in details I would like monkey patch this function.

So, the situation is similar to the following:

Function in the module

def function_in_module():
    # do some stuff
    return 'ok'

Part of my code that I would like testing

from dir_1.dir_2.dir_3.module_name import function_in_module
class ExampleClass():
    def __init__(self):
        # do some stuff
        self.var_x = function_in_module()
        # do some stuff again

Test class

from dir_1.dir_2.dir_3 import module_name
class TestClass(TestCase):
    de_monkey = {}
    mp = None

    def setUp(self):
        # save original one
        self.de_monkey['function_in_module'] = module_name.function_in_module()
        if self.mp is None:
            self.mp = MP()

    def tearDown(self):
        # rollback at the end
        module_name.function_in_module = self.de_monkey['function_in_module']

    def test_string(self):
        module_name.function_in_module = self.mp.monkey_function_in_module
        test_obj = ExampleClass()
        self.assertEqual(test_obj.var_x, 'not ok')

class MP(object):

    @staticmethod
    def monkey_function_in_module(self):
        return 'not ok'

As the assert statement shows, the expected result is 'not ok', but the result is 'ok'.

I have debugged about this and seems that the different way to call the functions is the reason because this monkey patch doesn't work.

In fact, if I try to call the function in ExampleClass in this way

self.var_x = module_name.function_in_module()

works correctly.

What am I missing? maybe it's a banality but it's driving me crazy

Thank you in advance

1

There are 1 answers

3
Daniel Roseman On BEST ANSWER

Your code under test imports function_in_module and references it directly. Changing the value of module_name.function_in_module has no effect on the code.

You should replace the function directly in the module that contains the code under test, not in the source module.

Note that your life would be easier if you used the mock library, although the question of where to patch would still be the same.