Jacob Jedryszek
Jacob Jedryszek

Reputation: 6470

Fake module used by other modules

Is any possibility to fake module, which is used(import) by other modules that I use in my tests?

Example: This is my test.py:

import unittest 
import module1
//test code here
module1.some_method()
//test code here

This is module1.py:

import module_i_want_to_fake
//module code here

Based on example: the question is: how can I fake module_i_want_to_fake in test.py

Upvotes: 1

Views: 1578

Answers (2)

macm
macm

Reputation: 2019

In python3 I do this:

Create simple fake class in a module

# module test.py
thismodule = sys.modules[__name__]
setattr(thismodule, "something", type("something", (), {}))

This is cool, but what you probably want is generate from a config data file.

Create fake class in a module from cfg file

# module test.py
import configparser

cfg = configparser.ConfigParser()
cfg.read("/path/to/fname.ini")

for section in cfg.sections():
    name = cfg[str(section)]['name']
    setattr(thismodule, name, type(name, (), {}))

Ok, now let's try in module1

# Import only the main module
import test

# now you can use as you want
test.something

Enjoy!!

Upvotes: 0

abarnert
abarnert

Reputation: 365637

When you do an import foo, if sys.modules['foo'] already exists, the interpreter just returns that instead of doing a fresh import.

So, to fake out module1's import statement, just get the value filled in before you load module1. This is a bit hacky, but very simple. For example:

mytest.py:

import sys
import unittest 
import my_fake_module
sys.modules['module_i_want_to_fake'] = my_fake_module
import module1
//test code here
module1.some_method()
//test code here

module1.py:

import module_i_want_to_fake
print(module_i_want_to_fake)

This will print out something like this:

<module 'my_fake_module' from 'my_fake_module.pyc'>

If you need to fake out module1 more thoroughly (even if it tries to introspect the module), you can create a new module (via types.ModuleType) with the code from my_fake_module but the name 'module_i_want_to_fake', and any other changes you want.

If you need to do this more dynamically than can be accomplished by just renaming modules statically in advance, you can build an import hook, as described in PEP 302. This requires you to reimplement a good chunk of the import mechanism, which is a huge pain in 2.x, but importlib in 3.1+ makes it a lot easier.

Fortunately, usually, you don't need to do either of these.

Upvotes: 3

Related Questions