单元测试中如何验证DTO仅指定字段被设置,其余未改动?
优雅验证DTO未修改指定外字段的方案
针对你需要验证sendCallbackToOneSystem仅设置id和status、其余字段保持默认值的需求,以下几种方案比逐个断言字段更简洁优雅:
方案一:使用AssertJ递归比较(推荐)
AssertJ的usingRecursiveComparison()支持忽略指定字段,直接和默认构造的空DTO对比,代码简洁且可读性强:
import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; class CallbackSenderTest { @Test void sendCallbackToOneSystem_shouldOnlySetIdAndStatus() { CallbackSender sender = new CallbackSender(); CallbackDTO result = sender.sendCallbackToOneSystem(); // 断言已设置的目标字段 assertThat(result.getId()).isEqualTo(1L); assertThat(result.getStatus()).isEqualTo("NEW"); // 对比其余字段与默认DTO一致 CallbackDTO defaultEmptyDTO = new CallbackDTO(); assertThat(result) .usingRecursiveComparison() .ignoringFields("id", "status") .isEqualTo(defaultEmptyDTO); } }
这个方法还能自动处理嵌套对象(比如CallbackDetails这类嵌套结构),如果后续DTO扩展字段,也不需要修改测试代码,只需要保证忽略的字段列表正确即可。
方案二:自定义反射工具类(无依赖场景)
如果项目中没有引入AssertJ,可通过反射遍历字段,排除指定字段后验证其余字段为默认值:
import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; import java.lang.reflect.Field; import java.util.Arrays; import java.util.HashSet; import java.util.Set; class CallbackSenderTest { @Test void sendCallbackToOneSystem_shouldOnlySetIdAndStatus() { CallbackSender sender = new CallbackSender(); CallbackDTO result = sender.sendCallbackToOneSystem(); assertThat(result.getId()).isEqualTo(1L); assertThat(result.getStatus()).isEqualTo("NEW"); // 验证除id、status外的字段均为默认值 assertNonExcludedFieldsAreDefault(result, "id", "status"); } private void assertNonExcludedFieldsAreDefault(Object obj, String... excludedFields) { Set<String> excluded = new HashSet<>(Arrays.asList(excludedFields)); for (Field field : obj.getClass().getDeclaredFields()) { if (excluded.contains(field.getName())) continue; field.setAccessible(true); try { Object fieldValue = field.get(obj); // 针对CallbackDTO的字段类型(包装类、引用类型),默认值均为null assertThat(fieldValue).isNull(); // 若存在基本类型(如int),需额外判断:比如int默认0,可添加类似判断 } catch (IllegalAccessException e) { throw new RuntimeException("反射访问字段失败", e); } } } }
内容的提问来源于stack exchange,提问作者snej0keee
相关产品推荐
相关产品推荐

