Mockito测试JSR-380层级对象级联验证失效问题求助
让我来帮你拆解问题根源,一步步解决这个验证失效的问题:
核心问题分析
1. 分组验证范围不匹配(最关键原因)
你的AAssembler类标注了@Validated({RequiringLanguageCode.class}),这意味着Spring的验证机制只会触发属于RequiringLanguageCode分组的约束规则。而C类中的@NotEmpty注解没有指定groups属性,默认归属javax.validation.groups.Default分组——这个分组不在当前验证的范围内,所以C类的约束完全不会被触发。
2. Mock对象的辅助影响
虽然Mockito mock本身不会直接阻止验证,但用mock对象模拟请求参数时,会脱离真实对象的实例结构,可能让验证框架的反射逻辑出现预期外的行为(不过在你的场景中,这是次要问题,核心还是分组不匹配)。
针对性解决方案
方案1:给C类的约束添加目标分组
修改C类的@NotEmpty注解,将RequiringLanguageCode分组加入,这样在验证该分组时,C类的约束会被触发:
public class C { private String value1; private String value2; public C(String value1, String value2) { this.value1 = value1; this.value2 = value2; } @NotEmpty(groups = {Default.class, RequiringLanguageCode.class}) public String getValue1() { return value1; } @NotEmpty(groups = {Default.class, RequiringLanguageCode.class}) public String getValue2() { return value2; } }
这样既保留了默认分组的验证能力,也适配了RequiringLanguageCode分组的验证场景。
方案2:扩展AAssembler的验证分组范围
如果希望同时验证默认分组和RequiringLanguageCode分组,可以修改AAssembler的@Validated注解,包含两个分组:
@Validated({Default.class, RequiringLanguageCode.class}) public class AAssembler { public Response build(@Valid @NotNull A request) { // ... 业务逻辑实现 } }
这种方式会让验证机制同时触发两个分组的所有约束,C类的默认分组约束自然会生效。
方案3:使用真实对象测试验证逻辑(推荐)
测试验证逻辑时,用真实的对象实例替代Mockito mock,能更贴近生产环境的真实情况,避免mock带来的不确定性:
@Test public void test() { // 创建真实的C对象,模拟value1为空的场景 C token = new C("", "key"); // 创建真实的A请求对象 A request = new A("en", token); // 触发验证并断言异常 assertThatIllegalArgumentException().isThrownBy(() -> aAssembler.build(request)); }
这种方式更适合验证逻辑的正确性测试,mock更适合用来模拟依赖服务,而非请求参数本身。
另外,你遇到的javax.validation.ConstraintDeclarationException: HV000131异常,本质上也是因为约束分组不匹配导致的声明冲突,解决了分组问题后,这个异常也会随之消失。
内容的提问来源于stack exchange,提问作者Manuel Glez

