spring boot中自定义验证的参数化junit测试

Parameterized junit test of custom validation in springboot

我在 springboot 中有这个验证器,当整数不在 1 和 3 之间时会出错,我正在使用 addConstraintViolation 从属性文件打印消息

public class SizeValidator implements ConstraintValidator<SizeValidation, Integer> {
    private int maxSize = 500;
    private int minSize = 1;

    @Override
    public void initialize(SizeValidation constraintAnnotation) {
        maxSize = constraintAnnotation.mxSize();
        minSize = constraintAnnotation.minSize();
    }

    @Override
    public boolean isValid(Integer givenSize, ConstraintValidatorContext context) {
        if (givenSize > maxSize || givenSize<= minPageSize) {
            addConstraintViolation(givenSize, "{Size.wrongSize.message}", context);
            return false;
        }
        return true;
    }

    private void addConstraintViolation(Integer givenSize, String errorMessage, ConstraintValidatorContext context) {
        final HibernateConstraintValidatorContext customContext = context.unwrap(HibernateConstraintValidatorContext.class);
        customContext.addExpressionVariable("givenSize", givenSize);

        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(errorMessage)
                .addConstraintViolation();
    }
}

在我的 validation.properties

Size.wrongSize.message=Value of size ${givenSize} should be between 1 and 3

我想为它编写一个参数化的 junit 测试,如下所示,但是它 returns nullpointerexception 请问我哪里做错了?

 java.lang.NullPointerException
      at sizeValidator.addConstraintViolation(SizeValidator.java:33)

intellij 说它在位置

context.buildConstraintViolationWithTemplate(errorMessage) .addConstraintViolation();

import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext;
    import org.junit.Test;
    import org.junit.experimental.runners.Enclosed;
    import org.junit.runner.RunWith;
    import org.junit.runners.Parameterized;
    
    import javax.validation.ConstraintValidatorContext;
    import java.util.Arrays;
    import java.util.Collection;
    
    import static org.junit.Assert.assertTrue;
    import static org.mockito.ArgumentMatchers.anyString;
    import static org.mockito.ArgumentMatchers.eq;
    import static org.mockito.Mockito.mock;
    import static org.mockito.Mockito.when;
    
        @RunWith(Enclosed.class)
        public class SizeValidatorTest{
        
            @RunWith(Parameterized.class)
            public static class TestValidEntries {
                private SizeValidator validator = new SizeValidator();
                private Integer val;
        
        
                public TestValidEntries(Integer val) {
                    super();
                    this.val = val;
                }
        
                @Test
                public void test() {
                    assertTrue(isValid(val));
                }
        
                @Parameterized.Parameters(name = "{index} Valid: {0}")
                public static Collection data() {
                    return Arrays.asList(
                            -1, 501
                    );
                }
        
                public boolean isValid(Integer value) {
                    final HibernateConstraintValidatorContext context = mock(HibernateConstraintValidatorContext.class);
                    when(context.unwrap(HibernateConstraintValidatorContext.class)).thenReturn(context);
                    when(context.addExpressionVariable(eq("nonUnique"), anyString())).thenReturn(context);
                    when(context.getDefaultConstraintMessageTemplate()).thenReturn("template");
                    final ConstraintValidatorContext.ConstraintViolationBuilder builder = mock(ConstraintValidatorContext.ConstraintViolationBuilder.class);
                    when(context.buildConstraintViolationWithTemplate("template")).thenReturn(builder);
        
                    when(builder.addPropertyNode(anyString())).thenReturn(mock(ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext.class));
        
                    return validator.isValid(value, context);
                }
        
            }
        }

问题出在 context 模拟的配置中。

您的配置显示:

when(context
      .buildConstraintViolationWithTemplate(
          "template"))
.thenReturn(builder);

但是您在被测代码中传递的字符串是:"{Size.wrongSize.message}" 因为这个字符串不匹配 mock returns null.


更好的方法是在测试方法的 arrange 部分(或 setup) 特定匹配器(或值)仅与测试方法的 assert 部分中的 Mockito.verify() 结合使用。