2012-09-25 43 views
7

假设我们有一个只存在于生产阶段的模块系统。在测试这些模块时不存在。但是我仍然想为使用这些模块的代码编写测试。我们还假设我知道如何模拟这些模块中的所有必要对象。问题是:我如何方便添加模块存根到当前层次?如何模拟不存在的模块的层次结构?

这是一个小例子。我想测试的功能被放置在一个名为actual.py文件:

actual.py: 


def coolfunc(): 
    from level1.level2.level3_1 import thing1 
    from level1.level2.level3_2 import thing2 
    do_something(thing1) 
    do_something_else(thing2) 

在我的测试套件我已经有我需要的一切:我有thing1_mockthing2_mock。另外我有一个测试功能。我需要的是将level1.level2...添加到当前模块系统中。就像这样:

tests.py 

import sys 
import actual 

class SomeTestCase(TestCase): 
    thing1_mock = mock1() 
    thing2_mock = mock2() 

    def setUp(self): 
    sys.modules['level1'] = what should I do here? 

    @patch('level1.level2.level3_1.thing1', thing1_mock) 
    @patch('level1.level2.level3_1.thing1', thing2_mock) 
    def test_some_case(self): 
    actual.coolfunc() 

我知道我可以包含其他对象等对象代替sys.modules['level1']。但它对我来说似乎有很多代码。我认为必须有更简单更漂亮的解决方案。我无法找到它。

回答

9

因此,没有人帮助我解决问题,我决定自己解决。 Here是一个名为surrogate的微库,它允许为不存在的模块创建存根。

库可以与mock这样使用:

from surrogate import surrogate 
from mock import patch 

@surrogate('this.module.doesnt.exist') 
@patch('this.module.doesnt.exist', whatever) 
def test_something(): 
    from this.module.doesnt import exist 
    do_something() 

首先@surrogate装饰创建不存在的模块存根,然后@patch装饰可以改变它们。正如@patch,@surrogate装饰器可以“复数”使用,从而桩住多个模块路径。所有存根仅在装饰函数的生命周期中存在。

如果任何人有任何使用这个库,这将是伟大的:)