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

使用AssertJ的containsOnly()比较自定义对象数组失败问题咨询

问题:AssertJ的containsOnly()对自定义对象数组不生效?

先看我的自定义对象定义:

@Accessors(chain = true)
@Getter
@Setter
@AllArgsConstructor
@ToString
public class SocialLink {
    private String platform;
    private String link;
}

测试代码如下:

SocialLink[] arr1 = new SocialLink[] {
    new SocialLink("Facebook", "Facebook Link"),
    new SocialLink("Google", "Google Link")
};
SocialLink[] arr2 = new SocialLink[] {
    new SocialLink("Google", "Google Link"),
    new SocialLink("Facebook", "Facebook Link")
};
assertThat(arr1).containsOnly(arr2);

运行后抛出断言错误:

java.lang.AssertionError: Expecting: <[SocialLink(platform=Facebook, link=Facebook Link), SocialLink(platform=Google, link=Google Link)]> to contain only: <[SocialLink(platform=Google, link=Google Link), SocialLink(platform=Facebook, link=Facebook Link)]> elements not found: <[SocialLink(platform=Google, link=Google Link), SocialLink(platform=Facebook, link=Facebook Link)]> and elements not expected: <[SocialLink(platform=Facebook, link=Facebook Link), SocialLink(platform=Google, link=Google Link)]>

明明containsOnly()对字符串数组能正常工作,为什么自定义对象数组就不行呢?


解答

这个问题我之前也碰到过,核心原因其实是对象相等性的判断逻辑在搞鬼!

为什么字符串数组没问题?

String类已经默认重写了equals()和hashCode()方法,它比较的是字符串的内容而非对象的内存地址。所以哪怕是两个不同的String实例,只要内容一致,equals()就会返回true,AssertJ也就会认为它们是相同的元素。

为什么自定义对象不行?

你的SocialLink类没有重写equals()和hashCode(),这时候会沿用父类Object的默认实现——只比较对象的内存地址。你在arr1和arr2里创建的SocialLink都是new出来的全新实例,内存地址完全不同,所以AssertJ会把它们判定为完全不同的元素,自然断言失败。

两种快速解决办法

1. 用Lombok注解自动生成相等性判断逻辑

给SocialLink类加上@EqualsAndHashCode注解,Lombok会自动根据类中的字段(这里是platform和link)生成对应的equals()和hashCode()方法:

@Accessors(chain = true)
@Getter
@Setter
@AllArgsConstructor
@ToString
@EqualsAndHashCode // 新增这个注解
public class SocialLink {
    private String platform;
    private String link;
}

这样一来,只要两个SocialLink对象的platform和link内容一致,equals()就会返回true,containsOnly()就能正常识别匹配的元素了。

2. 手动指定AssertJ的元素比较器

如果不想修改实体类,也可以在断言时手动指定比较逻辑,比如用usingElementComparator():

assertThat(arr1)
    .usingElementComparator((o1, o2) -> {
        if (o1.getPlatform().equals(o2.getPlatform()) && o1.getLink().equals(o2.getLink())) {
            return 0;
        }
        return 1;
    })
    .containsOnly(arr2);

或者用AssertJ提供的更简洁的字段比较器:

assertThat(arr1)
    .usingElementComparatorComparingOnlyFields("platform", "link")
    .containsOnly(arr2);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:07:44