是否有可能伪造模块,我在测试中使用的其他模块使用(导入)?
实施例: 这是我的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
基于示例:问题是:如何在test.py中伪造module_i_want_to_fake
答案 0 :(得分:3)
执行import foo
时,如果sys.modules['foo']
已经存在,则解释器只返回该值而不是重新导入。
因此,要伪造module1
的{{1}}语句,只需在加载import
之前获取值。这有点hacky,但很简单。例如:
mytest.py:
module1
module1.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
这将打印出类似这样的内容:
import module_i_want_to_fake
print(module_i_want_to_fake)
如果您需要更彻底地伪造<module 'my_fake_module' from 'my_fake_module.pyc'>
(即使它试图反省模块),您可以使用module1
中的代码创建一个新模块(通过types.ModuleType
)但名称为my_fake_module
,以及您想要的任何其他更改。
如果您需要更加动态地执行此操作,而不是事先通过静态重命名模块来实现,则可以构建导入挂钩,如PEP 302中所述。这需要你重新实现导入机制的一大块,这在2.x中是一个巨大的痛苦,但3.1+中的importlib
使它变得更容易。
幸运的是,通常,您不需要执行其中任何一项。
答案 1 :(得分: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, (), {}))
好的,现在让我们尝试一下module1
# Import only the main module
import test
# now you can use as you want
test.something
享受!!