修补来自不同模块的多个方法(使用Python模拟)

时间:2014-12-03 11:45:05

标签: python unit-testing

我的模块的结构:

foo: 
  - load()  # from DB


bar:
  - check() # with user
  - take_action() 

我想通过模拟加载和检查来测试take_action(它在执行操作之前基本上加载值并检查用户)。

这是嘲笑:

mock_load  = Mock(side_effects=[<>, <>, <>]) # different data sets
mock_check = Mock(return_value=True)  # User approval

如何使用patch.multiple使用Python 2.6实现此目的?

with patch.multiple(??):
    # proceed to test
    take_action

1 个答案:

答案 0 :(得分:10)

简短的回答是,你不能使用patch.multiple()来做。如patch.multiple中所述,所有参数都将应用于所有创建的模拟,并且所有参数必须是同一对象的属性。您必须通过单个补丁调用来执行此操作。

不幸的是,您使用的是python 2.6,因此您只需使用python: create a "with" block on several context managersMultiple context `with` statement in Python 2.6中指向的nestedcontextlib

使用@patch作为装饰器可能更简洁明了:

@patch("foo.load",side_effects=["a","b","c"])
@patch("bar.check",return_value=True)
def test_mytest(mock_check,mock_load):
    take_action()
    assert mock_load.called
    assert mock_check.called

如果您在测试类的所有测试中都需要它,您可以装饰该类并在所有测试方法中使用模拟:

@patch("foo.load",side_effects=["a","b","c"])
@patch("bar.check",return_value=True)
class TestMyTest(unittest.TestCase)
    def test_mytestA(self,mock_check,mock_load):
        take_action()
        self.assertTrue(mock_load.called)
        self.assertTrue(mock_check.called)

    def test_mytestA(self,mock_check,mock_load):
        mock_check.return_value = False
        take_action()
        self.assertTrue(mock_load.called)
        self.assertTrue(mock_check.called)

最后,您可以使用withcontextlib来完成第一个示例:

from contextlib import nested

with nested(patch("foo.load",side_effects=["a","b","c"]), patch("bar.check",return_value=True)) as (mock_load, mock_check):
    take_action()
    assert mock_load.called
    assert mock_check.called

......或者手工筑巢......

with patch("foo.load",side_effects=["a","b","c"]) as mock_load:
    with patch("bar.check",return_value=True)) as mock_check:
        take_action()
        assert mock_load.called
        assert mock_check.called

我觉得装饰器最易读且易于使用。