SpringBoot Bean验证批注

问题描述

我目前正在为服务中的bean验证编写一些@SpringBoottest。

@Data
@Document
public final class supplier {

    @Id
    @NotEmpty
    private String supplierId;
    ...
    @NotEmpty
    private String hash;
    ....
}

测试

注释:

@ExtendWith(SpringExtension.class)
@SpringBoottest(classes = {Application.class},webEnvironment = SpringBoottest.WebEnvironment.MOCK)

 @Test
    void testValidation() {
        supplier invalidsupplier = supplierTestDataUtil.createsupplier("1234");
        invalidsupplier.setsupplierId(null);

        //works
        assertThrows(ConstraintViolationException.class,() -> supplierService.publish(invalidsupplier));

        //works
        assertThrows(ConstraintViolationException.class,() -> supplierService.persist(invalidsupplier));
        
        //works not
        assertThrows(ConstraintViolationException.class,() -> supplierService.saveAndPublish(invalidsupplier));

        //works
        assertThrows(ConstraintViolationException.class,() -> supplierService.delete(invalidsupplier));
    }

服务:

@Transactional
public supplier saveAndPublish(@NotNull supplier supplier) {
    supplier.setHash(messageDigester.digest(supplier));
    supplier persisted = persist(supplier);
    publish(supplier);
    return persisted;
}

@Transactional
public supplier persist(@Valid @NotNull supplier supplier) {
    return repository.save(supplier);
}

saveAndFlush上的供应商此时必须无效,因为将在该方法生成并设置所需的哈希。 不过,我的期望是也会引发ConstraintViolationException,因为我还调用了persist和publish方法并传递了无效的文档。

我的观点是,您可以在同一类中绕过BeanValidation。

解决方法

ConstraintViolationException将被弹簧Validator抛出,如果您“手动”调用persist,则不会使用该弹簧。如果从Spring上下文中调用persist,则@Valid批注将告诉Spring根据类的验证约束来验证对象。

您可以:

  1. 始终“手动”验证hash(无@NotEmpty注释)
  2. 在调用supplier.setHash(messageDigester.digest(supplier));之前先调用saveAndPublish,然后将@Valid批注添加到Supplier的{​​{1}}参数中
  3. 将Validator实例作为字段添加到您的服务中,并在要验证的供应商上手动调用它(当然,在设置散列后使用saveAndPublish的情况下)
  4. 实施两种不同类型的saveAndPublish,例如Supplier(未经AddSupplier验证;由hash使用)和saveAndPublish(具有{{1 }}正在验证;由EditSupplier使用)

(这可能是不完整的列表)