我正处于一个项目中,我们开始重构一些庞大的代码库.立即出现的一个问题是每个文件都导入了很多其他文件.我如何以优雅的方式在我的单元测试中模拟这个而不必改变实际的代码,这样我就可以开始编写单元测试了?
举个例子:带有我要测试的函数的文件,导入其他十个文件,这些文件是我们软件的一部分而不是python核心库.
我希望能够尽可能单独运行单元测试,现在我只测试不依赖于正在导入的文件中的内容的函数.
感谢所有的答案.
我从一开始就不知道自己想做什么,但现在我想我知道了.
问题是有些导入只有在整个应用程序运行时才有可能因为某些第三方自动魔法而导致.所以我不得不在我用sys.path指出的目录中为这些模块制作一些存根
现在,我可以在单元测试文件中导入包含我要编写测试功能的文件,而不会抱怨缺少模块.
如果要在导入模块的同时确保它不导入任何内容,则可以替换__import__
内置函数.
例如,使用此类:
class ImportWrapper(object): def __init__(self, real_import): self.real_import = real_import def wrapper(self, wantedModules): def inner(moduleName, *args, **kwargs): if moduleName in wantedModules: print "IMPORTING MODULE", moduleName self.real_import(*args, **kwargs) else: print "NOT IMPORTING MODULE", moduleName return inner def mock_import(self, moduleName, wantedModules): __builtins__.__import__ = self.wrapper(wantedModules) try: __import__(moduleName, globals(), locals(), [], -1) finally: __builtins__.__import__ = self.real_import
在你的测试代码中import myModule
,写下:
wrapper = ImportWrapper(__import__) wrapper.mock_import('myModule', [])
的第二个参数mock_import
是模块名称的列表,你不希望内部模块的导入.
此示例可以进一步修改为例如导入除期望之外的其他模块,而不是仅仅导入它,甚至可以使用您自己的某个自定义对象模拟模块对象.