Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python, unit-testing and mocking imports

I am in a project where we are starting refactoring some massive code base. One problem that immediately sprang up is that each file imports a lot of other files. How do I in an elegant way mock this in my unit test without having to alter the actual code so I can start to write unit-tests?

As an example: The file with the functions I want to test, imports ten other files which is part of our software and not python core libs.

I want to be able to run the unit tests as separately as possible and for now I am only going to test functions that does not depend on things from the files that are being imported.

Thanks for all the answers.

I didn't really know what I wanted to do from the start but now I think I know.

Problem was that some imports was only possible when the whole application was running because of some third-party auto-magic. So I had to make some stubs for these modules in a directory which I pointed out with sys.path

Now I can import the file which contains the functions I want to write tests for in my unit-test file without complaints about missing modules.

like image 600
Rickard Lindroth Avatar asked Oct 07 '08 13:10

Rickard Lindroth


2 Answers

If you want to import a module while at the same time ensuring that it doesn't import anything, you can replace the __import__ builtin function.

For example, use this class:

class ImportWrapper(object):
    def __init__(self, real_import):
        self.real_import = real_import

    def wrapper(self, wantedModules):
        def inner(moduleName, *args, **kwargs):
            if moduleName in wantedModules:
                print "IMPORTING MODULE", moduleName
                self.real_import(*args, **kwargs)
            else:
                print "NOT IMPORTING MODULE", moduleName
        return inner

    def mock_import(self, moduleName, wantedModules):
        __builtins__.__import__ = self.wrapper(wantedModules)
        try:
            __import__(moduleName, globals(), locals(), [], -1)
        finally:
            __builtins__.__import__ = self.real_import

And in your test code, instead of writing import myModule, write:

wrapper = ImportWrapper(__import__)
wrapper.mock_import('myModule', [])

The second argument to mock_import is a list of module names you do want to import in inner module.

This example can be modified further to e.g. import other module than desired instead of just not importing it, or even mocking the module object with some custom object of your own.

like image 146
DzinX Avatar answered Oct 09 '22 16:10

DzinX


If you really want to muck around with the python import mechanism, take a look at the ihooks module. It provides tools for changing the behavior of the __import__ built-in. But it's not clear from your question why you need to do this.

like image 37
Alex Coventry Avatar answered Oct 09 '22 14:10

Alex Coventry