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

单元测试中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认为这是两个不同的类

解决步骤:

  1. 统一所有模块中ApiException的导入路径,确保测试代码和业务代码使用完全一致的导入语句,比如都用from APIs.api_exceptions import ApiException
  2. 检查项目的sys.path配置,避免出现重复的模块路径导致类被多次加载
  3. 可以在测试和业务代码中分别打印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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 15:07:46