2013-03-13 133 views
1

是否有任何可能伪造模块,这是由我在测试中使用的其他模块使用(导入)?其他模块使用的假模块

举例: 这是我的test.py:

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

这是module1.py:

import module_i_want_to_fake 
//module code here 

基于例如:问题是:如何在测试我可以假module_i_want_to_fake。 py

+1

是什么原因?你可以'将module1导入为m1'或者使用其他名称作为参考。 – ninMonkey 2013-03-13 20:42:41

+0

但是当我导入module1时,module1会导入module_i_want_to_fake,但我想导入my_fake_module – 2013-03-13 20:47:06

+0

因此,您希望从'module1'之外拦截其“import”语句,以便您可以替换不同的模块? – abarnert 2013-03-13 20:47:42

回答

3

当你做一个import foo,如果sys.modules['foo']已经存在,解释器只是返回,而不是做一个新鲜的进口。

因此,要伪造module1import声明,只需在加载module1之前获取填充的值。这有点哈克,但很简单。例如:

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:如果您需要假了

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

import module_i_want_to_fake 
print(module_i_want_to_fake) 

这将打印出这样的事情module1更彻底(即使它试图反思模块),你可以创建一个新的模块(通过types.ModuleType),代码为my_fake_module,但名称为'module_i_want_to_fake',以及其他所需的更改。

如果您需要更动态地完成此操作,而不是仅通过事先静态地重命名模块即可完成此操作,则可以构建导入挂钩,如PEP 302中所述。这需要你重新实现一大块导入机制,这在2.x中是一个巨大的痛苦,但是在3.1+中的importlib使得它更容易。

幸运的是,通常情况下,您不需要执行其中任何一项。

0

在python3我这样做:

模块

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

这是很酷的创建简单的假冒类,但你可能想要的是从配置数据文件产生。

从CFG文件中创建一个模块中的假类

# 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,(), {})) 

好了,现在让我们尝试在模块1

# Import only the main module 
import test 

# now you can use as you want 
test.something 

享受!