如何用Python单元测试检测是否抛出了嵌套异常?
检测Python异常链中的嵌套异常
问题原因
你的测试失败是因为second_fn实际抛出的是Outer异常,Inner只是这个异常的触发原因(通过raise Outer from e显式关联)。assertRaises默认只会检查顶层抛出的异常类型,不会自动遍历异常链。
解决方案
要验证异常链中的嵌套异常,你需要捕获顶层异常后,通过Python的异常链属性来检查内部异常:
方法1:使用assertRaises上下文管理器
利用上下文管理器获取抛出的Outer异常实例,然后检查其__cause__属性(因为你用了from e显式关联,所以用__cause__;如果是隐式链,用__context__):
import unittest class Inner(Exception): pass class Outer(Exception): pass def first_fn(): raise Inner def second_fn(): try: first_fn() except Exception as e: raise Outer from e class MyTestCase(unittest.TestCase): def test_case(self): with self.assertRaises(Outer) as exception_context: second_fn() # 验证内部异常类型 self.assertIsInstance(exception_context.exception.__cause__, Inner) # 可选:如果需要验证异常实例或消息,可以进一步断言 # self.assertEqual(str(exception_context.exception.__cause__), "预期消息") if __name__ == '__main__': unittest.main()
方法2:手动捕获异常
如果你更习惯手动处理异常捕获,也可以这样写:
class MyTestCase(unittest.TestCase): def test_case(self): try: second_fn() except Outer as outer_exc: # 检查内部异常是否为Inner类型 self.assertIsInstance(outer_exc.__cause__, Inner) else: # 如果没有抛出Outer异常,测试失败 self.fail("未抛出预期的Outer异常")
关键说明
__cause__:当使用raise NewExc from OriginalExc时,NewExc.__cause__会指向OriginalExc,用于显式的异常链。__context__:当异常在except块中隐式触发时(没有from),会设置这个属性,代表上下文异常。
这样就能准确验证异常链中的嵌套异常了。
内容的提问来源于stack exchange,提问作者samarendra chandan bindu Dash
相关产品推荐
相关产品推荐

