Search code examples
pythonpython-modulepython-mockpython-unittest

How to load my fake module every time when `import a real module` in python?


I need to test on a function.py, and in this function.py there is a import statement:

from my.functions import cleaner
from my.functions import worker

I don't want the cleaner get imported because it's very complicated. So I try to set the sys.path :

sys.path.insert(0, './fakes')

in fakes module, a my.functions.cleaner also exists there but with no function, that works but it will also impact worker, I really want the worker works for me.

So my question is there any way to "mock" this cleaner to my fake cleaner, I need my fake cleaner replace it every time import cleaner.

I tried sys.modules but failed.


Solution

  • If you're trying to dynamically replace a function, you can do so with an assignment statement, I.E.:

    To see this in action check out this example:

    import my.functions

    /my

    functions.py

    def cleaner():
        print("Cleaner from functions!")
    
    def worker():
        print("Worker from functions!")
    

    base.py

    import my.functions
    
    def cleaner():
        print("Replacement fake cleaner!")
    
    my.functions.cleaner = cleaner
    
    
    def method_to_test():
        from my.functions import cleaner
        from my.functions import worker
        cleaner()
        worker()
    
    
    if __name__ == "__main__":
        method_to_test()
    

    Python loads the my.functions module into sys.modules, then on subsequent from imports gets objects from the already loaded module, so we can set a mock function before your function does its import.