单元测试中isinstance()判断ApiException失效问题求助
单元测试中异常类型验证失败问题排查
[已解决,查看下方我的回答]
我在单元测试中遇到问题:测试处理API的代码在HTTP状态码异常时是否抛出指定异常,该代码用于Jira与GitLab的自动合并流程。
异常类定义
import inspect class ApiException(Exception): def __init__(self, response) -> None: self.http_code = response.status_code self.message = response.text.replace("\n", " ") self.caller = inspect.getouterframes(inspect.currentframe(), 2)[1] self.caller_file = self.caller[1] self.caller_line = self.caller[2] def __str__(self) -> str: return f"Error code {self.http_code} with message '{self.message}' in file {self.caller_file} line {self.caller_line}"
GitLab API调用抛出异常的代码段
if response.ok: return MergeRequest(json.loads(response.text)) else: raise ApiException(response=response)
单元测试代码
class TestException(unittest.TestCase): def test_raise_exception(self): api_call = ApiCall() api_response = ApiCallResponse() api_response.ok = False api_response.status_code = 401 api_call.get_with_header = MagicMock(return_value=api_response) gitlab = GitLab(logger=TestLogger, api_call=api_call) try: gitlab.get_project_by_url("https://git.mycompany.de/group/project") assert False except Exception as err: TestLogger.info(type(err)) TestLogger.info(isinstance(err, ApiException)) assert isinstance(err, ApiException)
测试失败错误信息
Merge_Service_Test | try: Merge_Service_Test | gitlab.get_project_by_url("https://git.mycompany.de/group/project") Merge_Service_Test | assert False Merge_Service_Test | except Exception as err: Merge_Service_Test | TestLogger.info(err) Merge_Service_Test | > assert isinstance(err, ApiException) Merge_Service_Test | E assert False Merge_Service_Test | E + where False = isinstance(ApiException(), ApiException)
问题核心
我需要验证抛出的是否为正确的异常,但isinstance()返回False。打印type(err)显示为<class 'APIs.api_exceptions.ApiException'>,这是正确的异常类型。请问问题出在哪里,该如何解决?
我的回答
这个问题的根源是异常类被重复导入,导致测试代码中引用的ApiException和被测试代码中抛出的ApiException不是同一个类对象。
常见场景:
- 被测试代码中通过
from APIs.api_exceptions import ApiException导入 - 测试代码中通过相对路径或不同的导入方式(比如
from .api_exceptions import ApiException)导入,导致Python认为这是两个不同的类
解决步骤:
- 统一所有模块中
ApiException的导入路径,确保测试代码和业务代码使用完全一致的导入语句,比如都用from APIs.api_exceptions import ApiException - 检查项目的
sys.path配置,避免出现重复的模块路径导致类被多次加载 - 可以在测试和业务代码中分别打印
id(ApiException),如果两个id不同,就说明是重复导入的问题
另外,单元测试中可以改用unittest自带的异常断言方法,代码更简洁:
def test_raise_exception(self): # ... 其他初始化代码 with self.assertRaises(ApiException): gitlab.get_project_by_url("https://git.mycompany.de/group/project")
内容的提问来源于stack exchange,提问作者DasMoorhuhn
相关产品推荐
相关产品推荐

