其他模块使用的假模块
问题描述:
是否有任何可能伪造模块,这是由我在测试中使用的其他模块使用(导入)?其他模块使用的假模块
举例: 这是我的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
答
当你做一个import foo
,如果sys.modules['foo']
已经存在,解释器只是返回,而不是做一个新鲜的进口。
因此,要伪造module1
的import
声明,只需在加载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
使得它更容易。
幸运的是,通常情况下,您不需要执行其中任何一项。
答
在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
享受!
是什么原因?你可以'将module1导入为m1'或者使用其他名称作为参考。 – ninMonkey 2013-03-13 20:42:41
但是当我导入module1时,module1会导入module_i_want_to_fake,但我想导入my_fake_module – 2013-03-13 20:47:06
因此,您希望从'module1'之外拦截其“import”语句,以便您可以替换不同的模块? – abarnert 2013-03-13 20:47:42