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

如何在单元测试中断言两个包含数组字段的UserDto对象数组相等

如何在单元测试中断言两个包含数组字段的UserDto对象数组相等

咱们先理清楚你的场景:你有一个UserDto记录类,里面包含String[] roles数组字段,现在要在单元测试里断言两个UserDto数组完全相等,但直接用assertArrayEquals可能会踩坑——因为默认情况下,Java记录类的equals方法对数组字段是比较引用而非内容的,哪怕两个数组内容一模一样,只要是不同的数组对象,比较结果就是false,导致断言失败。

先把你提供的代码整理一下,方便参考:

你的UserDto类

public record UserDto(
    @NotBlank Long id,
    @NotBlank String name,
    @NotBlank String lastname,
    @NotBlank String email,
    @NotBlank String[] roles) {
}

测试用的UserDto实例

UserDto basicUserDto = new UserDto(
    2L,
    "donquixote",
    "doflamingo",
    "doffy@acme.com",
    new String[]{"ROLE_USER"}
);

UserDto accountantUserDto = new UserDto(
    3L,
    "monkey",
    "d-luffy",
    "luffy@acme.com",
    new String[]{"ROLE_ACCOUNTANT"}
);

// 假设你有这样的预期和实际数组
UserDto[] expectedDtoArray = new UserDto[]{basicUserDto, accountantUserDto};
UserDto[] actualDtoArray = // 你的测试代码返回的目标数组

接下来给你两种可行的解决方案,按需选择:


方案一:自定义UserDto的equals和hashCode方法

既然默认的record equals不处理数组内容比较,咱们手动重写它,用Arrays.equals来比较roles数组的内容。这样不管数组是不是同一个对象,只要内容一致就会判定相等:

import java.util.Arrays;
import java.util.Objects;
import jakarta.validation.constraints.NotBlank;

public record UserDto(
    @NotBlank Long id,
    @NotBlank String name,
    @NotBlank String lastname,
    @NotBlank String email,
    @NotBlank String[] roles) {

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserDto userDto = (UserDto) o;
        return Objects.equals(id, userDto.id) &&
               Objects.equals(name, userDto.name) &&
               Objects.equals(lastname, userDto.lastname) &&
               Objects.equals(email, userDto.email) &&
               Arrays.equals(roles, userDto.roles);
    }

    @Override
    public int hashCode() {
        int result = Objects.hash(id, name, lastname, email);
        result = 31 * result + Arrays.hashCode(roles);
        return result;
    }
}

修改之后,直接用JUnit的assertArrayEquals就可以正常断言了:

import static org.junit.jupiter.api.Assertions.assertArrayEquals;

// ...

assertArrayEquals(expectedDtoArray, actualDtoArray);

这个方案适合需要在多个场景下比较UserDto对象的情况,一次修改全场景生效。


方案二:用AssertJ的递归比较(无需修改业务代码)

如果你不想改动UserDto的代码,可以用AssertJ断言库的递归比较功能,它会自动深入到对象的每个字段,包括数组内容进行比较:

首先确保你的项目里引入了AssertJ依赖(Maven示例):

<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.24.2</version>
    <scope>test</scope>
</dependency>

然后在测试代码里这样写:

import static org.assertj.core.api.Assertions.assertThat;

// ...

assertThat(actualDtoArray)
    .usingRecursiveComparison()
    .isEqualTo(expectedDtoArray);

这个方案更灵活,不用修改业务代码,特别适合临时的单元测试场景,而且AssertJ的错误提示也更友好,会告诉你具体是哪个字段不相等。


备注:内容来源于stack exchange,提问作者eniesIobby

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 09:03:03