【问题标题】:Overriding Python mock's patch decorator覆盖 Python mock 的补丁装饰器
【发布时间】:2012-10-05 20:55:47
【问题描述】:

我有一个 Python TestCase 类,除了一个之外,所有测试方法都需要以相同的方式修补对象。另一种方法需要来自同一对象的一些其他行为。我正在使用mock,所以我这样做了:

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    @mock.patch('method_to_patch', mock.Mock(return_value=2))
    def test_override(self):
         (....)

但这不起作用。当test_override 运行时,它仍然会从类装饰器中调用修补后的行为。

经过大量调试,我发现在TestSuite构建期间,test_override周围的@patchTests周围的那个之前被调用,并且由于mock按顺序应用补丁,类装饰器覆盖了方法装饰器。

这个顺序正确吗?我期待相反的结果,但我不确定如何覆盖补丁......也许使用with 声明?

【问题讨论】:

  • test_override 必须在Tests 中吗?我可以想象有另一个TestCase 用于test_override 和类似的测试。如果您希望所有method_to_patch 做一件事,但为test_override 做另一件事,那么我也可以想象拥有另一个TestCase 课程是合理的。这也将解决您的问题,并使代码对其他开发人员更具可读性(与“打补丁”相比)。
  • @SimeonVisser 将test_override 移动到另一个类并不是一个真正的选择,因为我们用于构建测试的规则。它们都是相对于同一个视图的测试,所以我们将它们放在一个 TestCase

标签: python testing mocking


【解决方案1】:

好吧,事实证明,睡个好觉和洗个冷水澡让我重新思考了整个问题。 我对模拟的概念还很陌生,所以它还没有完全正确。

问题是,没有必要将补丁覆盖到模拟对象。这是一个模拟对象,这意味着我可以让它做任何事情。所以我的第一次尝试是:

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    def test_override(self):
         method_to_patch.return_value = 2
         (....)

这行得通,但有改变所有后续测试的返回值的副作用。于是我尝试了:

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    def test_override(self):
         method_to_patch.return_value = 2
         (....)
         method_to_patch.return_value = 1

它就像一个魅力。但似乎代码太多了。于是我就走上了上下文管理的道路,就像这样:

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    def test_override(self):
         with mock.patch('method_to_patch', mock.Mock(return_value=2):
             (....)

我认为它看起来更清晰,更简洁。

关于 patch 装饰器的应用顺序,实际上是正确的顺序。就像从下向上应用堆叠的装饰器一样,方法装饰器应该在类装饰器之前调用。我想这是有道理的,我只是期待相反的行为。

无论如何,我希望这对将来像我这样可怜的新手有帮助。

【讨论】:

    猜你喜欢
    • 2017-01-31
    • 2019-09-12
    • 2017-10-05
    • 2022-12-09
    • 2021-12-20
    • 2013-01-19
    • 2021-07-19
    • 2014-12-13
    • 1970-01-01
    相关资源
    最近更新 更多