【问题标题】:Mock parent class __init__ method模拟父类 __init__ 方法
【发布时间】:2015-11-27 18:24:28
【问题描述】:

我正在尝试在一个派生自另一个类的类上编写一些单元测试,但是我在模拟父类 init 方法时遇到了一些困难,这是你做不到的,所以我正在寻找建议.

这是我的课程的示例

导入的.py

class Imported():
    def __init__(self, a="I am Imported"):
        print("a:{}".format(a))

父.py

from Imported import Imported

class Parent(object):

    parent_list = ["PARENT"]

    def __init__(self, a="I am Parent"):
        imported = Imported(a)

派生的.py

from Parent import Parent

class Derived(Parent):

    Parent.parent_list.append("DERIVED")

在我的单元测试中,当我从 Derived 类 Derived() 实例化一个对象时,我想验证 Parent.parent_list == ["PARENT", "DERIVED"]。

这两个解决方案都不起作用

test_Derived.py

import unittest
from mock import patch

from Derived import Derived


class test_Derived(unittest.TestCase):

    @patch("Derived.Parent.__init__")
    def test_init_001(self, mock_parent_init):
        a = Derived("I am Derived")
        mock_parent_init.assert_called_with("I am Derived")
        self.assertEquals(a.parent_list, ["PARENT", "DERIVED"])

    @patch("Derived.Imported.Imported")
    def test_init_002(self, mock_parent_init):
        a = Derived("I am Derived")
        mock_parent_init.assert_called_with("I am Derived")
        self.assertEquals(a.parent_list, ["PARENT", "DERIVED"])

test_init_001 失败

TypeError: __init__() should return None, not 'MagicMock'

test_init_002 失败

ImportError: No module named Parent.Imported

有什么建议吗?

【问题讨论】:

  • 为什么Parent.__init__ 需要被嘲笑?为什么不只是模拟Imported
  • 你的第二个测试需要模拟Parent.Imported
  • 最后但同样重要的是,您修改了Parent.parent_list ,所以Parent.parent_listDerived.parent_list 都引用同一个对象。所以Parent.parent_list 现在包含"DERIVED"。您可能想为Derived 创建一个副本:parent_list = Parent.parent_list + ["DERIVED"]。您的测试可能需要对此进行检查。

标签: python python-2.7 unit-testing mocking


【解决方案1】:

对于第一种解决方案,将__init__方法的返回值更改为None

@patch("Derived.Parent.__init__")
def test_init_001(self, mock_parent_init):
    mock_parent_init.return_value = None  # <---
    a = Derived("I am Derived")
    mock_parent_init.assert_called_with("I am Derived")
    self.assertEquals(a.parent_list, ["PARENT", "DERIVED"])

对于第二种解决方案,补丁Parent.Imported

@patch("Parent.Imported")  # <---
def test_init_002(self, mock_parent_init):
    a = Derived("I am Derived")
    mock_parent_init.assert_called_with("I am Derived")
    self.assertEquals(a.parent_list, ["PARENT", "DERIVED"])

【讨论】:

  • 我试图通过模拟__init__ 和方法(我们称之为foo())来测试一个类是否使用正确的参数进行了初始化,然后在该实例上正确调用了一个方法。在我将 __init__ 的返回值设置为 None 之前,模拟的 foo 方法没有注册任何调用。 (我认为这是因为代码中的初始化被 __init__ 的模拟破坏了,尽管将 side_effect 设置为原始的 __init__ 方法不起作用 - foo() 模拟仍然没有注册任何调用。)谢谢这几乎打败了我!
  • 在你的第一个解决方案而不是mock_parent_init.return_value = None 行中,你可以在补丁定义中指定这个东西,即。 @patch("Derived.Parent.__init__", return_value=None).
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-27
  • 2020-09-23
  • 1970-01-01
  • 1970-01-01
  • 2021-02-09
  • 1970-01-01
相关资源
最近更新 更多