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

Python单元测试模拟CustomError无法触发except块问题

模拟异常捕获的单元测试问题分析

原业务代码

class ClassB:
    def do_something(self):
        temp = ClassA()
        try:
            return temp.methodA()
        except CustomError:
            return False

(注:你提供的原代码遗漏了class关键字,且do_something方法缺少self参数,实际运行会报错,已修正)

你的测试问题

你尝试模拟ClassA.methodA抛出CustomError,验证do_something返回False,但第一个测试失败,第二个用pytest.raises的测试虽然通过,却根本没触发业务代码里的except块。

失败的测试代码

import pytest
from unittest.mock import patch

@pytest.fixture
def class_b_fixture():
    return ClassB()

@patch('ClassB.ClassA')
def test_do_something_error(class_a_mock, class_b_fixture):
    class_a_mock.return_value.methodA.side_effect = CustomError()
    assert not class_b_fixture.do_something()

错误原因

问题出在**side_effect的赋值方式**:

  • 当你写CustomError()时,是在测试代码执行到这一行就直接实例化了异常,而不是在调用methodA时抛出。
  • unittest.mock的规则是:如果side_effect是一个异常实例,它会在访问methodA属性的时候就抛出,而不是调用methodA()的时候。
  • 这就导致异常在进入do_something的try块之前就触发了,根本没机会被except捕获,所以第一个测试会报错异常未被捕获,第二个测试用pytest.raises能抓到这个提前跑出的异常,自然就通过了,但完全不符合你的测试预期。

正确的测试写法

把side_effect赋值为异常类本身,而不是实例:

@patch('ClassB.ClassA')
def test_do_something_error(class_a_mock, class_b_fixture):
    # 赋值异常类,而非实例
    class_a_mock.return_value.methodA.side_effect = CustomError
    assert not class_b_fixture.do_something()

这样设置后,当调用temp.methodA()时才会抛出CustomError,业务代码里的except块会正常捕获并返回False,测试就能通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 00:15:38