Kotlin函数数组展开符无法适配AssertJ的Java Function可变参数
AssertJ extracting断言包装函数的类型匹配问题
问题代码
尝试封装AssertJ的extracting断言,当前实现如下:
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.groups.Tuple fun <T, R> checkObjectsHaveExactPropertyValue( objectsList: List<T>, properties: Array<Function1<T, R>>, expectedPropertyValue: R ) { assertThat(objectsList) .extracting(*properties) .containsOnly(Tuple.tuple(expectedPropertyValue)) }
编译错误
传入多个属性提取器时触发编译错误:
Kotlin: None of the following functions can be called with the arguments supplied: public open fun <V : Any!> extracting(p0: Function<in T!, TypeVariable(V)!>!): AbstractListAssert<*, (MutableList<out TypeVariable(V)!>..List<TypeVariable(V)!>?), TypeVariable(V)!, ObjectAssert<TypeVariable(V)!>>! defined in org.assertj.core.api.ListAssert public final fun extracting(vararg p0: Function<in T!, *>!): AbstractListAssert<*, (MutableList<out Tuple!>..List<Tuple!>?), Tuple!, ObjectAssert<Tuple!>>! defined in org.assertj.core.api.ListAssert public open fun extracting(vararg p0: String!): AbstractListAssert<*, (MutableList<out Tuple!>..List<Tuple!>?), Tuple!, ObjectAssert<Tuple!>>! defined in org.assertj.core.api.ListAssert public open fun extracting(p0: String!): AbstractListAssert<*, (MutableList<out Any!>..List<Any!>?), Any!, ObjectAssert<Any!>>! defined in org.assertj.core.api.ListAssert public open fun <V : Any!, EXCEPTION : Exception!> extracting(p0: ThrowingExtractor<in T!, TypeVariable(V)!, TypeVariable(EXCEPTION)!>!): AbstractListAssert<*, (MutableList<out TypeVariable(V)!>..List<TypeVariable(V)!>?), TypeVariable(V)!, ObjectAssert<TypeVariable(V)!>>! defined in org.assertj.core.api.ListAssert
已尝试的调试方式
- 直接写
.extracting(properties[0], properties[1])可编译,但无法支持动态多参数 - 更换Iterable类型(List、ArrayList等),错误一致
- 将参数改为
vararg properties: Function1<T, R>,错误相同 - 将参数改为
properties: Array<(T) -> R>,错误相同
解决方案
问题核心是AssertJ的extracting(vararg Function<in T!, *>!)重载要求传入Java原生的java.util.function.Function类型,而非Kotlin自带的Function1或lambda类型。同时原代码中Tuple.tuple(expectedPropertyValue)仅传入单个值,当匹配多个属性时会不匹配Tuple的元素数量,需要调整为接收多个预期值。
修正后的代码
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.groups.Tuple import java.util.function.Function fun <T> checkObjectsHaveExactPropertyValues( objectsList: List<T>, vararg properties: Function<in T, *>, vararg expectedValues: Any? ) { assertThat(objectsList) .extracting(*properties) .containsOnly(Tuple.tuple(*expectedValues)) }
调用示例
断言列表中所有对象的name和age属性都等于"Alice"和25:
data class Person(val name: String, val age: Int) val people = listOf(Person("Alice", 25), Person("Alice", 25)) checkObjectsHaveExactPropertyValues( objectsList = people, properties = arrayOf( Function { it.name }, Function { it.age } ), expectedValues = arrayOf("Alice", 25) )
简化lambda调用的技巧
如果想直接用Kotlin lambda,可借助自定义扩展函数转换为Java Function:
// 自定义扩展函数,将Kotlin lambda转为Java Function fun <T, R> ((T) -> R).toJavaFunction(): Function<T, R> = Function(this) // 简化调用写法 checkObjectsHaveExactPropertyValues( objectsList = people, properties = arrayOf( { it.name }.toJavaFunction(), { it.age }.toJavaFunction() ), expectedValues = arrayOf("Alice", 25) )
内容的提问来源于stack exchange,提问作者galaher0
相关产品推荐
相关产品推荐

