如何模拟从函数导入但在sys.path中不存在的模块?

时间:2017-01-26 12:55:28

标签: python mocking python-unittest

我是unittest代码,其中包含执行本地导入的方法。

def function_under_test():
    import unknown.dependency

(我没有在.py文件的顶部使用导入,因为在调用该函数时它可能存在也可能不存在。)

以通常的方式模拟unknown.dependency只有在sys.path的某处可以找到它时才有效。否则,对patch的调用失败(它拒绝模拟它无法查看的内容):

with mock.patch('unknown.dependency'):
    function_under_test()
>>> ImportError: No module named 'unknown'

文档建议我应该修补使用模块的命名空间 - 在本例中为function_under_test。但是,当该命名空间是一个函数时,这不会削减它。对patch的调用成功,但实际的import语句仍然引用了原始的,不存在的unknown模块,该模块无法找到。

with mock.patch('method_under_test.unknown'):
    print("fails")
>>> ImportError: No module named 'unknown'

那么,如果模块本身不存在并且是从函数导入的话,如何用mock替换依赖模块?

1 个答案:

答案 0 :(得分:8)

仅模拟导入

简单的方法是将import语句移动到一个单独的函数中。

def get_dependency():
    import unknown.dependency
    return unknown.dependency

def function_under_test():
    module = get_dependency()
    # use module

这样可以很容易地模拟出那个'帮助者'功能。这样做的缺点是需要更改被测代码。它确实有效:

with mock.patch('get_dependency'):
    function_under_test()

模拟模块

正如here所述,您可以将模拟模块直接添加到sys.modules,以便Python可以找到它,无论它是否存在于sys.path中。

with mock.patch.dict('sys.modules', unknown=mock.MagicMock()):
    function_under_test()