How can I mock any function which is not being called directly?

我的梦境 提交于 2021-02-10 15:15:25

问题


TL;DR

How can I patch or mock "any functions that are not being called/used directly"?

Sceneario

I have a simple unit-test snippet as

# utils/functions.py
def get_user_agents():
    # sends requests to a private network and pulls data
    return pulled_data


# my_module/tasks.py
def create_foo():
    from utils.functions import get_user_agents
    value = get_user_agents()
    # do something with value
    return some_value


# test.py
class TestFooKlass(unittest.TestCase):
    def setUp(self):
        create_foo()

    def test_foo(self):
        ...

Here in setUp() method I am calling get_user_agents() function indirectly by calling create_foo(). During this execution I have got socket.timeout exception since get_user_agents() tried to access a private network.

So, how can I manipulate the return data or the entire get_user_agents function during the test?

Also, is there any way to persists this mock/patch during the whole test suite execution?


回答1:


It does not matter that you call the function indirectly - important is to patch it as it is imported. In your example you import the function to be patched locally inside the tested function, so it will only be imported at function run time. In this case you have to patch the function as imported from its module (e.g. 'utils.functions.get_user_agents'):

class TestFooKlass(unittest.TestCase):
    def setUp(self):
        self.patcher = mock.patch('utils.functions.get_user_agents',
                                  return_value='foo')  # whatever it shall return in the test 
        self.patcher.start()  # this returns the patched object, i  case you need it
        create_foo()

    def tearDown(self):
        self.patcher.stop()

    def test_foo(self):
        ...

If you had imported the function instead at module level like:

from utils.functions import get_user_agents

def create_foo():
    value = get_user_agents()
    ...

you should have patched the imported instance instead:

        self.patcher = mock.patch('my_module.tasks.get_user_agents',
                                  return_value='foo')

As for patching the module for all tests: you can start patching in setUp as shown above, and stop it in tearDown.



来源:https://stackoverflow.com/questions/62502151/how-can-i-mock-any-function-which-is-not-being-called-directly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!