提问人:developer747 提问时间:10/13/2023 最后编辑:Olivierdeveloper747 更新时间:11/18/2023 访问量:143
Java 自定义约束验证器在单元测试中失败,并显示“未设置目标验证器”错误
Java custom constraints validator fails in unit tests with "No target Validator set" error
问:
我有springboot应用程序,它像这样连接validatorFactoryBean
private LocalValidatorFactoryBean validatorFactoryBean;
@Autowired
public void setValidatorFactoryBean(LocalValidatorFactoryBean validatorFactoryBean) {
this.validatorFactoryBean = validatorFactoryBean;
}
我在类 Car 上定义了自定义验证器,我像这样运行验证。
Set<ConstraintViolation<Car>> constraintViolations = validatorFactoryBean.validate(myCar);
所有这些都很好。但是当我尝试通过单元测试来测试它时,在线
validatorFactoryBean.validate(myCar)
我收到错误“未设置目标验证器”。
这就是我在testng单元测试中设置validatorFactoryBean的方式
@InjectMocks
LocalValidatorFactoryBean validatorFactoryBean;
我通过调用 setValidatorFactoryBean setter 将其传递给我正在测试的类。
在调试时,我意识到这个 validatorFactoryBean 并不知道主代码中的所有 ConstraintValidator 实现。
如何使 validatorFactoryBean 了解所有 ConstraintValidator 实现?
答:
@InjectMocks
只是一个嘲讽的东西,从来不懂春天。这就像您手动创建一个没有任何弹簧集成的一样。LocalValidatorFactoryBean
要正确配置,您可以通过使用 to 自动配置 bean 验证的东西来做到这一点。LocalValidatorFactoryBean
@SpringBootTest
@ImportAutoConfiguration
@SpringBootTest
public class ValidationTest{
@Configuration
@ImportAutoConfiguration(ValidationAutoConfiguration.class)
@ComponentScan(basePackages = { "my.app.root.package" })
public static class Config {
}
@Autowired
LocalValidatorFactoryBean validatorFactoryBean;
@Test
void test(){
}
}
我还建议你使用 ,如 Ken 的回答中所述。但是,如果出于某种原因您不想这样做,那么只要所有自定义约束验证器都具有默认的 no-args 构造函数,使用以下代码初始化的对象就应该适用于测试:@SpringBootTest
LocalValidatorFactoryBean
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
(选项 1)如果 是由 Spring 容器创建的,则在 afterPropertiesSet()
阶段执行一些额外的逻辑。LocalValidatorFactoryBean
您可以通过自己调用此方法来复制此方法。例如:
@BeforeEach
void setUp() {
validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
}
(选项 2)但是,这是一种黑客攻击,因为Spring Boot创建的默认值包含额外的定制器和消息插值器。如果您不关心这一点,那么使用底层 JSR-380 bean 验证器可能会更干净。例如:LocalValidatorFactoryBean
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
请注意,这将是一种不同的类型,但它也包含具有相同签名的方法。validator
validate()
(选项 3)如果你确实关心 Spring 提供的额外设置,那么你可以编写一个 Spring 集成测试。我不建议使用,因为你会使你的测试膨胀。@SpringBootTest
您真正需要的只是包含必要的自动配置:SpringExtension
@ExtendWith(SpringExtension.class)
@ImportAutoConfiguration(ValidationAutoConfiguration.class)
public class MyValidationTest {
@Autowired
private LocalValidatorFactoryBean validator;
}
评论