【问题标题】:patch multiple methods from different modules (using Python mock)修补来自不同模块的多个方法(使用 Python 模拟)
【发布时间】:2014-12-03 11:45:05
【问题描述】:

我的模块结构:

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

【问题讨论】:

    标签: python unit-testing


    【解决方案1】:

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

    不幸的是,您使用的是 python 2.6,因此您只能使用 nestedcontextlib 就像在 python: create a "with" block on several context managersMultiple context `with` statement in Python 2.6 中指出的那样。

    也许更清洁和简单的方法是使用@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
    

    我的感觉是装饰器是最易读和最容易使用的。

    【讨论】:

      猜你喜欢
      • 2021-09-17
      • 2022-07-06
      • 2021-08-31
      • 2020-06-17
      • 2018-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多