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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 15:07:21