其他模块使用的假模块

时间:2013-03-13 20:39:05

标签: python unit-testing mocking python-unittest

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

实施例: 这是我的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

2 个答案:

答案 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

享受!!