Search code examples
pythonpython-unittestpython-mockpython-unittest.mock

Mock global function call while importing


Suppose I have a file called a.py with code like

import mod1
mod1.a()

def b():
   print("hi")

Now if I want to mock fun b() then unittest.py while have import statement at top like

from a import b

at time of import mod1.a() will be called. How can I mock that call which is happening at the time of import.


Solution

  • Consider removing code from module top-level, by moving it to a block protected by

    if __name__ == '__main__':
        mod1.a()
        ... # the rest of your top level code
    

    This way the protected code does not get executed on imports, only when run directly.

    If you still need the call there and want to mock it, it is very simple. With files like this,

    # mod.py
    
    import mod1
    mod1.a()
    
    def b():
       print("hi")
    
    
    # mod1.py
    
    def a():
        print('Running a!')
    
    # test_1.py
    # Note: do not call unittest.py to a file.
    # That is the name of a module from the Python stdlib,
    # you actually need to use it and things will not work,
    # because Python tries to load your file not the library you need.
    
    from unittest.mock import patch
    
    with patch('mod1.a') as mock_a:
        ... # configure mock_a here if there is a need, for example
            # to set a fake a call result
        import mod
        ... # the rest of your testing code. Use `mock_a` if you want to
            # inspect `a` calls.
    

    Outside the with mod1.a is no longer mocked. There are other ways to start and stop mocking, you should look into the documentation. Before studying mock make sure you understand well how unittests work and how you can organize your tests.