You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python unittest.mock @patch装饰器模拟对象方法返回值失败问题排查

问题分析与解决方案

你遇到的问题核心在于Mock对象的实例化行为:当你用patch把DummyObject替换成你定义的dummy_patch这个Mock实例后,调用do.DummyObject()其实是触发了dummy_patch的__call__方法,而Mock的__call__默认会返回一个全新的Mock实例,不是你预先配置好的dummy_patch本身。

你之前设置的dummy_patch.foo.return_value = "9999"是作用在类级别的Mock上,但实际创建的tmp是这个Mock的调用返回值(新的Mock实例),这个新实例的foo方法并没有被设置返回值,所以它会返回默认的MagicMock对象,导致测试失败。


解决方法一:让Mock实例化时返回自身

修改你的dummy_patch配置,让它的__call__方法返回自己,这样do.DummyObject()就会直接返回你预先配置好的Mock对象:

import unittest
from unittest.mock import patch, Mock
import dummy_objects as do

dummy_patch = Mock(spec=do.DummyObject)
dummy_patch.foo.return_value = "9999"
# 关键:让Mock被实例化时返回自身
dummy_patch.__call__.return_value = dummy_patch

@patch("dummy_objects.DummyObject", new=dummy_patch)
class TestCaseOne(unittest.TestCase):
    def test_patching_foo(self):
        tmp = do.DummyObject()
        self.assertEqual(tmp.foo(), "9999")  # 现在测试会成功

解决方法二:在测试方法内配置实例的返回值

更推荐的方式是利用patch自动传入的Mock参数,直接配置实例的行为,这样代码更清晰,也不需要提前创建Mock:

import unittest
from unittest.mock import patch
import dummy_objects as do

@patch("dummy_objects.DummyObject")
class TestCaseOne(unittest.TestCase):
    def test_patching_foo(self, mock_dummy_class):
        # mock_dummy_class是被替换的DummyObject类的Mock
        # mock_dummy_class.return_value 就是调用DummyObject()得到的实例
        mock_dummy_class.return_value.foo.return_value = "9999"
        
        tmp = do.DummyObject()
        self.assertEqual(tmp.foo(), "9999")  # 测试通过

为什么原来的代码会失败?

再理一遍流程帮你理解:

  1. 你用patch把dummy_objects.DummyObject替换成了dummy_patch这个Mock。
  2. 当你执行tmp = do.DummyObject()时,本质是调用dummy_patch(),也就是Mock的__call__方法。
  3. Mock的__call__默认会生成一个新的Mock实例并返回,这个新实例和你之前配置的dummy_patch没有关系。
  4. 所以tmp.foo()调用的是这个新Mock的foo方法,而它没有被设置返回值,自然返回默认的MagicMock对象。

内容的提问来源于stack exchange,提问作者JonnyOhneha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 08:37:44