10

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

这是一个小例子。我要测试的功能放在一个名为的文件中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']用包含另一个对象的对象替换,依此类推。但这对我来说似乎有很多代码。我认为必须有更简单和更漂亮的解决方案。我只是找不到它。

4

2 回答 2

16

所以,没有人帮我解决我的问题,我决定自己解决。是一个名为的 micro-lib surrogate,它允许为不存在的模块创建存根。

Lib 可以这样使用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装饰器可以“复数”使用,从而存根多个模块路径。所有存根仅在修饰函数的生命周期内存在。

如果有人可以使用这个库,那就太好了:)

于 2012-09-27T21:40:14.767 回答
-1

您可以在patch()方法中使用“create”参数,如果该属性不存在,它将强制创建该属性。

于 2019-08-27T10:51:12.133 回答