提问者:小点点

自定义ConstraintValidator单元测试


我需要在我的自定义ConstraintValidator上进行验证,它使用了一些验证所需的@Inject,就像夸库的这个例子https://quarkus.io/guides/validation

@ApplicationScoped
public class MyConstraintValidator implements ConstraintValidator<MyConstraint, String> {

    @Inject
    MyService service;

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }

        return service.validate(value);
    }
}

当我运行应用程序时,我看到这是正确的验证,但我试图使用mockito进行单元测试,我无法使用默认Bean验证在默认值上模拟对象始终为空。

在夸克的例子中,单元测试仅用于集成。

这是我的实现

@ApplicationScoped
public class MyConstraintValidator implements ConstraintValidator<MyConstraint, String> {

    @Inject
    BookService service;

    @ConfigProperty(name = "my.property")
    int myLimit;

    public MyConstraintValidator(BookService service) {
        this.service = service;
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        System.out.println("myLimit property: " + myLimit);

        int limit = Integer.parseInt(value);
        if (limit < myLimit) {
            return service.validate(value);
        } else {
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(NAME_EMPTY).addConstraintViolation();
            return false;
        }

    }
}

用于测试自定义Validator的单元测试

    @Test
    void testAmountValidationWithContext() {

        BookRequest bookRequest = new BookRequest();
        bookRequest.setTitle("my title");
        bookRequest.setAuthor("my Author");
        bookRequest.setPages(2L);
        bookRequest.setAmount("11");

        //when:
        myConstraintValidator = new MyConstraintValidator(service);
        Mockito.when(service.validate(anyString())).thenReturn(true);

        //then:
        Set<ConstraintViolation<BookRequest>> violations = validator.validate(bookRequest);

        // verify that the context is called with the correct argument
        Mockito.verify(context).buildConstraintViolationWithTemplate(NAME_EMPTY);

    }

单元测试默认@NoBlank。

    @Test
    void testBeanValidationWithInvalidAmount() {
        BookRequest bookRequest = new BookRequest();
        bookRequest.setTitle("my title");
        bookRequest.setAuthor("my Author");
        bookRequest.setPages(2L);
        bookRequest.setAmount("AA");

        //when:
        Set<ConstraintViolation<BookRequest>> violations = validator.validate(bookRequest);

        //then:
        assertEquals(1, violations.size());
        assertEquals(NOT_EMPTY, violations.stream().findFirst().get().getMessage());
    }

第一单元测试工作得很好,我可以模拟对象并测试结果。

问题出在我的第二个测试中,当我尝试测试其他验证@NotNull,@Pattern时。在这个测试中,方法isValid()也被调用,这是我的问题,因为@ConfigProperty和@Inject总是空的,我无法模拟它们。

我已经在互联网上看到了几个例子,但不起作用,几乎是Spring,但我需要在夸克斯上进行自定义验证。

我如何实现自定义ConstraintValidator单元测试使用夸克?

有人有这样工作的例子吗?


共2个答案

匿名用户

将代码从字段注入更改为构造函数注入将使单元测试变得更加容易。

@ApplicationScoped
public class MyConstraintValidator implements ConstraintValidator<MyConstraint, String> {


    private final MyService service;
    private final int myLimit;

    public MyConstraintValidator(MyService service, @ConfigProperty(name = "my.property") int myLimit) {
       this.service = service;
       this.myLimit = myLimit;
    } 

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) 
    {
        if (value == null) {
            return true;
        }

        return service.validate(value);
    }
}

匿名用户

用我的实现更新了描述。但是继续这个问题。当我有我的自定义验证器的默认注释时,我不能使用

设置