如何扩展unittest.assertRaises实现自定义HTTP错误断言方法
自定义unittest HTTP异常断言方法实现方案
你需要借助上下文管理器实现自定义断言,核心逻辑是通过yield将执行权交给with块内的业务代码,待业务代码执行完成后再执行异常校验逻辑。
完整实现代码
同步场景实现
如果你的HTTP请求是同步调用,使用普通上下文管理器即可:
import json import unittest from contextlib import contextmanager # 你的自定义异常类 class MyHTTPClientError(Exception): def __init__(self, code, response): self.code = code self.response = response class MyTestCase(unittest.TestCase): @contextmanager def assertRaisesHTTPError(self, code: int, error_message: str): # 先捕获目标异常 with self.assertRaises(MyHTTPClientError) as er: # 暂停执行,将异常对象暴露给with语句的as变量,执行业务代码 yield er # 业务代码执行完成后做参数校验 self.assertEqual(er.exception.code, code) actual_error_msg = json.loads(er.exception.response.body)["error_description"] self.assertEqual(actual_error_msg, error_message)
异步场景实现
如果你的HTTP请求是异步调用(需要await执行),则使用异步上下文管理器:
import json import unittest from contextlib import asynccontextmanager class MyTestCase(unittest.TestCase): @asynccontextmanager async def assertRaisesHTTPError(self, code: int, error_message: str): with self.assertRaises(MyHTTPClientError) as er: yield er self.assertEqual(er.exception.code, code) actual_error_msg = json.loads(er.exception.response.body)["error_description"] self.assertEqual(actual_error_msg, error_message)
使用示例
同步场景调用
def test_sync_request(self): with self.assertRaisesHTTPError(404, "Not found") as er: my_http_request() # 同步调用HTTP请求
异步场景调用
注意异步场景需要将with改为async with:
async def test_async_request(self): async with self.assertRaisesHTTPError(404, "Not found") as er: await my_http_request() # 异步调用HTTP请求
原代码问题说明
最初的半成品代码错误点在于,在方法内部直接编写了with块,该块没有任何执行逻辑,无法捕获到外部with块中业务代码抛出的异常。使用上下文管理器的yield机制可以完美解决执行权流转的问题。
内容的提问来源于stack exchange,提问作者Thomas Schreiter
相关产品推荐
相关产品推荐

