如何在单元测试中断言两个包含数组字段的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
相关产品推荐
相关产品推荐

