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
相关产品推荐
相关产品推荐

