【问题标题】:Subclassing MagicMock in python在python中继承MagicMock
【发布时间】:2015-04-07 11:53:20
【问题描述】:

我有一个需要修补的类,它的工作原理与此类似

class Foo(object):
    def __init__(self, query):
        self._query = query

    def do_stuff(self):
        # do stuff with self._query

我将如何为 Foo 设置一个模拟类

foo = MockFoo(query)
foo.do_stuff()

返回一个模拟结果,但仍考虑为query 传入的数据。我想过像这样子类化MagicMock

class MockFoo(MagicMock):
    def __init__(self, query, *args, **kwargs):
        super(MagicMock, self).__init__(*args, **kwargs)
        self._query

    def do_stuff(self):
        mock_result = self._query * 10
        return MagicMock(return_value=mock_result)

但我不太清楚如何在实际的 TestCase 中应用 patch 以使用 MockFoo 而不是 MagicMock。我需要能够编写类似的测试。

with patch('x.Foo') as mock_foo:
    # run test code
    self.assertTrue(mock_foo.called)
    self.assertEqual(mock_foo.wait.return_value, 20)

我知道我可以使用普通的MagicMockautospec=True 或其他东西并覆盖每个方法的返回值,但是如果有一个模拟类可以用来替换生产类就好了一气呵成。关键是,必须在模拟方法中访问成员变量self._query,同时在构造函数中对其进行初始化(就像生产类一样)。

【问题讨论】:

  • 我认为这行不通,因为在某种程度上,您需要区分真实方法/属性和模拟方法/属性。诸如“调用”和“返回值”之类的东西是模拟的一部分,因此将它们添加到生产类的修改实例中是不可行的。我认为最好通过模拟你需要的东西并可能添加一些帮助代码来做到这一点。

标签: python python-3.x mocking python-unittest python-mock


【解决方案1】:

关于您的基本问题,答案是在patch 中使用new_callable 参数:

with patch('x.Foo', new_callable=MockFoo) as mock_foo:
    # run test code
    self.assertTrue(mock_foo.called)
    self.assertEqual(mock_foo.wait.return_value, 20)

如果您需要向MockFoo init 调用添加一些参数,请考虑patch 中未使用的每个参数都将传递给模拟构造函数(在您的情况下为MockFoo)。

如果您需要一个生产类的包装器,也许您找错地方了:mock 不是包装器。

当您模拟某些东西时,您并不是真的想知道您的模拟是如何工作的,而只是想知道您的代码如何使用它以及您的代码如何对模拟对象的答案做出反应。

【讨论】:

    猜你喜欢
    • 2011-03-15
    • 1970-01-01
    • 2016-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    • 1970-01-01
    相关资源
    最近更新 更多