为何Result对象会被额外包裹在另一个Result中?
为何Result对象会被额外包裹在另一个Result中?
这个问题的核心在于Kotlin的Result是inline值类,结合JUnit 5参数化测试的参数解析逻辑,触发了额外的装箱/拆箱操作,最终导致嵌套的Result<Result<Boolean>>。
具体原因
Kotlin的Result作为inline类,在JVM层面会被编译为底层基础类型(比如这里的Boolean),但保留了类型元信息。当你通过Arguments.of(Result.success(true))传递参数时:
- JUnit的参数解析器会把
Result实例解包成它的底层值true - 因为测试方法参数声明为
Result类型,JUnit又会自动把true重新包装成一个新的Result<Boolean> - 最终就出现了外层
Result包裹原本Result<Boolean>的嵌套情况
修复方案
方案1:用普通类包裹Result
创建一个简单的数据类封装Result,让JUnit直接处理普通类而非inline类:
import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource import java.util.stream.Stream // 用数据类封装Result,避免JUnit直接处理inline类 data class ResultHolder<T>(val value: Result<T>) class TestTest { companion object { @JvmStatic fun streamOfArguments(): Stream<Arguments> { return Stream.of( Arguments.of(ResultHolder(Result.success(true))) ) } } @ParameterizedTest @MethodSource("streamOfArguments") fun testArgumentParameter(holder: ResultHolder<Boolean>) { val actualResult = holder.value println(actualResult::class) // 输出class kotlin.Result actualResult.onSuccess { println(it) // 输出true } } }
方案2:将Result包装进数组传递
Arguments.of()接收可变参数,单个inline类会被特殊处理,但传入数组时,JUnit会直接保留数组内的原类型:
import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource import java.util.stream.Stream class TestTest { companion object { @JvmStatic fun streamOfArguments(): Stream<Arguments> { return Stream.of( // 把Result包装进数组,跳过JUnit的inline类解包逻辑 Arguments.of(arrayOf(Result.success(true))) ) } } @ParameterizedTest @MethodSource("streamOfArguments") fun testArgumentParameter(actualResult: Result<Boolean>) { println(actualResult::class) // 输出class kotlin.Result actualResult.onSuccess { println(it) // 输出true } } }
两种方案都能让你拿到原本的Result<Boolean>实例,彻底避免嵌套问题。
内容的提问来源于stack exchange,提问作者Eaton Emmerich
相关产品推荐
相关产品推荐

