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

如何正确Mock类实例调用的外部函数?pytest单元测试求助

问题描述

编写单元测试时,在test_model.py中定义TestPlayerAnomalyDetectionModel类,实例化PlayerAnomalyDetectionModel后调用.fit方法。该方法内部会调用发送API请求的get_player_account_status函数,需要Mock这个函数并通过side_effect返回不同值,但尝试两种patch路径都未生效,实际API请求仍被触发:

  • 使用@mock.patch('get_player_labels.get_player_account_status'),Mock未生效
  • 改用@mock.patch('model.get_player_account_status'),实际函数仍被调用
解决方案

1. 确认Patch的正确路径

你的核心思路是对的:必须Patch函数被调用位置的引用。model.py中通过from get_player_labels import get_player_account_status导入函数,因此Patch路径'model.get_player_account_status'是正确的,但需要排查模块导入冲突问题:

  • 测试文件中同时导入了import mock和from unittest.mock import patch,容易导致模块混淆,建议删除import mock,统一使用unittest.mock下的patch装饰器。

2. 修正Mock的使用逻辑

你当前的side_effect用法有误:get_player_account_status本身没有返回值,它是通过修改传入的account_statuses字典来完成状态设置的,直接给side_effect传字符串列表不会产生预期效果。

正确的Mock方式是模拟函数的行为,直接修改传入的字典参数:

from unittest.mock import patch

# ... 其他代码保持不变

@patch('model.get_player_account_status')
def test_fit(self, mock_get_player_account_status):
    # 定义要依次返回的状态列表
    status_sequence = [
        'open', 'open', 'tosViolation', 'tosViolation', 'tosViolation', 'closed', 
        'open', 'open', 'tosViolation', 'tosViolation', 'tosViolation', 'closed', 
    ]
    
    # 模拟函数行为:修改传入的account_statuses字典
    def mock_set_account_status(player, account_statuses):
        account_statuses[player] = status_sequence.pop(0)
    
    mock_get_player_account_status.side_effect = mock_set_account_status
    
    self.model.fit(self.sample_train_data, generate_plots=False)
    
    # 可选:验证Mock被调用的次数是否符合预期
    self.assertEqual(mock_get_player_account_status.call_count, 12)

3. 排查实例化时机问题

确保PlayerAnomalyDetectionModel实例是在Patch生效之后创建的:你的setUp方法在测试方法之前执行,而patch装饰器会包裹整个测试方法,因此实例化顺序是正确的。如果有其他fixture提前创建了模型实例,会导致Mock失效,需要检查fixture的执行顺序。

4. 调试Mock是否生效的技巧

在测试方法中添加打印,确认Mock对象是否被正确注入:

@patch('model.get_player_account_status')
def test_fit(self, mock_get_player_account_status):
    # 打印Mock对象,若输出类似<MagicMock name='get_player_account_status' id='xxxx'>则说明注入成功
    print(mock_get_player_account_status)
    # 后续测试代码...

如果输出原始函数对象,说明Patch路径错误或时机不对。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 01:15:08