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

AssertJ提取列表后调用first()返回List而非预期对象问题

解决AssertJ中.first()返回List而非预期String的问题

你遇到的错误很典型:

java.lang.AssertionError: [List check first element] Expecting: <["Malaysia"]> to be an instance of: <java.lang.String> but was instance of: <java.util.ArrayList>

本来期望.first()返回String类型的元素,结果它返回了整个List<String>,这是因为extracting()的行为和你预期的不一样。

问题根源

当你对单个Region对象调用.extracting(Region::getCountries)时,AssertJ并不会直接把提取到的List<String>作为断言目标——它会把这个列表包装成一个只包含该列表的Iterable。也就是说:

  • .hasSize(1)验证的是这个包装后的Iterable的大小(确认我们成功提取到了一个属性值),而不是countries列表本身的元素数量。
  • .first()取的是这个Iterable的第一个元素,也就是整个List<String>,而非列表里的"Malaysia"字符串。

解决方案

这里有几种简洁的修复方式:

方案1:用flatExtracting()展开集合属性

flatExtracting()会自动拆解集合类型的属性,直接把集合内的元素作为断言的目标Iterable。这样后续的断言就完全符合你的预期了:

assertThat(asia)
    .isInstanceOfSatisfying(Region.class, regionRequirement)
    .flatExtracting(Region::getCountries)
    .hasSize(1)
    .first()
    .isInstanceOfSatisfying(String.class, countryRequirement);

方案2:嵌套断言操作List元素

如果你想保留extracting(),可以在提取到List后,再对List本身进行嵌套断言,明确获取它的第一个元素:

assertThat(asia)
    .isInstanceOfSatisfying(Region.class, regionRequirement)
    .extracting(Region::getCountries)
    .first() // 获取到整个countries列表
    .hasSize(1)
    .first() // 获取列表中的第一个String元素
    .isInstanceOfSatisfying(String.class, countryRequirement);

方案3:用satisfies()直接断言属性

这种方式最直观,直接针对Region的countries属性做断言,完全绕开extracting()的包装问题:

assertThat(asia)
    .isInstanceOfSatisfying(Region.class, regionRequirement)
    .satisfies(region -> assertThat(region.getCountries())
        .hasSize(1)
        .first()
        .isInstanceOfSatisfying(String.class, countryRequirement));

总结

推荐使用方案1或方案3,代码更简洁易读,也更符合AssertJ的设计意图。

内容的提问来源于stack exchange,提问作者Rashidi Zin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:22:38