python中MagicMock的子类化

python中MagicMock的子类化,python,python-3.x,mocking,python-unittest,python-mock,Python,Python 3.x,Mocking,Python Unittest,Python Mock,我有一个需要修补的类,其工作原理与此类似 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传入的数据。我想到像这样子类化M

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

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)
但是我不太明白如何在实际的测试用例中应用
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)

我知道我可以将plain
MagicMock
autospec=True
一起使用,然后覆盖每个方法的返回值,但是如果有一个模拟类,我就可以用它一次性替换生产类,那就太好了。关键位是,必须在mock方法中访问成员变量
self.\u query
,同时在构造函数中对其进行初始化(就像生产类一样)

关于您的基本问题答案是使用
new\u callable
参数:

如果您需要对<代码> MOCKFOO init调用添加一些参数,请考虑在<代码>修补程序中使用的每个参数都将是PasSit到模拟构造函数(<代码> Mokfoo在您的情况下)。

如果您需要为生产类创建一个包装器,那么您可能找错了地方:mock不是包装器


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

我认为这不起作用,因为在某种程度上你需要区分真实的方法/属性和模拟的方法/属性。像“called”和“return_value”这样的东西是mock的一部分,所以将它们添加到生产类的修改实例中是不可行的。我认为最好按照您所说的那样,模拟您需要的内容,并可能添加一些帮助程序代码。
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)