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

Python中如何测试被Mock的数据类调用?解决测试匹配错误

问题原因

当你用unittest.mock.patch替换Person类时,被patch后的Person是一个Mock对象,它会完整跟踪所有调用链:

  1. 每次Person()实例化操作,本质是调用Mock类的__call__方法,会被记录为call();
  2. 实例化后调用work()方法,会被Mock记录为call().work()——这是因为Mock会把实例化返回的子Mock对象的方法调用,以链式形式记录在父Mock的调用记录里。

你的测试断言只预期两次call(),但实际mock_calls里会包含call()和call().work()各两次,自然会匹配失败。

正确测试方法

根据你的需求(验证两次实例化+两次work调用),可以分两种方式编写测试:

方式1:直接验证实例化次数和方法调用次数

这是最简洁的写法,分别验证类被实例化的次数,以及每个实例的work方法被调用的次数:

import unittest
from unittest.mock import patch
from your_module import run_person  # 替换成你的实际模块名

class TestRunPerson(unittest.TestCase):
    @patch("your_module.Person")  # 注意路径要和run_person里导入Person的路径一致
    def test_run_person(self, mock_person):
        run_person()
        
        # 验证Person被实例化了2次
        mock_person.assert_called_times(2)
        
        # 验证所有实例的work方法总共被调用2次
        mock_person.return_value.work.assert_called_times(2)

方式2:精确验证调用顺序(如果需要)

如果你需要严格验证实例化和方法调用的顺序,可以直接检查完整的调用链:

import unittest
from unittest.mock import patch, call
from your_module import run_person

class TestRunPerson(unittest.TestCase):
    @patch("your_module.Person")
    def test_run_person(self, mock_person):
        run_person()
        
        # 预期的完整调用链:实例化→调work,再实例化→调work
        expected_calls = [
            call(),
            call().work(),
            call(),
            call().work()
        ]
        mock_person.assert_has_calls(expected_calls, any_order=False)

关键注意点

  • patch的路径必须和run_person函数中导入Person的路径一致,否则patch不会生效;
  • mock_person.return_value代表每次实例化返回的Mock实例,所以它的work方法调用次数就是所有实例调用work的总次数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 20:12:17