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

如何在Java AssertJ中实现Kotlin扩展函数校验自定义异常code属性?

解决AssertJ Kotlin扩展函数获取异常实例的问题

要搞定这个问题,核心是你可能不知道ThrowableAssertAlternative本身就提供了公开的actual属性,直接就能拿到实际抛出的异常对象,不需要绕弯子。下面给你两种实用的实现方案:

方案1:针对MyException的专属扩展函数

既然你已经用assertThatExceptionOfType(MyException::class.java)指定了异常类型,那完全可以写一个针对性的扩展函数,省去类型转换的麻烦:

// 直接限定为MyException的断言类型,不用泛型兼容所有Throwable
private fun ThrowableAssertAlternative<MyException>.withErrorCode(expectedErrorCode: Int): ThrowableAssertAlternative<MyException> {
    // 直接通过actual拿到MyException实例,校验code属性
    assertThat(this.actual.code)
        .isEqualTo(expectedErrorCode)
    
    // 返回this保证链式调用的连贯性
    return this
}

你的测试代码可以直接按预期使用:

@Test
fun `Creating webdto without name fails`() {
    assertThatExceptionOfType(MyException::class.java)
        .isThrownBy { service.create(WebDto.apply { this.name = null }) }
        .withMessageContaining("Bean validation error.")
        .withErrorCode(1) // 现在能正常校验code了
}

方案2:通用扩展函数(支持所有带code的异常)

如果你的项目里有多个自定义异常都带code属性,可以先定义统一接口,再写通用扩展函数,扩展性更强:

首先定义接口并让MyException实现它:

interface CodedException {
    val code: Int
}

// 修改MyException实现该接口
class MyException: Exception, CodedException {
    override val code: Int

    constructor(message: String, code: Int) : super(message) {
        this.code = code
    }
    constructor(cause: Throwable, code: Int) : super(cause) {
        this.code = code
    }
}

然后编写通用扩展函数:

private fun <T : Throwable> ThrowableAssertAlternative<T>.withErrorCode(expectedErrorCode: Int): ThrowableAssertAlternative<T> {
    // 把实际异常转换为CodedException,转换失败时抛出清晰的断言错误
    val codedException = this.actual as? CodedException
        ?: failWithMessage("Expected exception to implement CodedException, but got ${actual?.javaClass?.simpleName}")
    
    assertThat(codedException.code)
        .isEqualTo(expectedErrorCode)
    
    return this
}

这种方式能支持所有实现了CodedException接口的异常,复用性拉满。

关键提示

  • ThrowableAssertAlternative的actual属性是公开可用的,在Kotlin扩展函数里直接用this.actual就能拿到抛出的异常实例。
  • 要保持链式调用,扩展函数必须返回this,这样就能和AssertJ原有的断言方法连贯使用。

内容的提问来源于stack exchange,提问作者Manu Zi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:15:51