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

Posted

技术标签:

【中文标题】spring boot中自定义验证的参数化junit测试【英文标题】:Parameterized junit test of custom validation in springboot 【发布时间】:2021-09-05 07:00:58 【问题描述】:

我在 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=大小 $givenSize 的值应该在 1 之间 和 3

我想为它编写一个参数化的junit测试,但它返回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);
                
        
            
        

【问题讨论】:

您到底想要什么细节?它关于在变量级别验证整数值,我添加了错误消息 你声称得到了NullPointerException,堆栈跟踪在哪里? 查看更新帖 【参考方案1】:

问题出在context mock 的配置中。

你的配置说:

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

但是您在被测代码中传递的字符串是:"Size.wrongSize.message" 因为这个字符串不匹配模拟返回null


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

【讨论】:

能否根据我的配置提供可行的解决方案?

以上是关于spring boot中自定义验证的参数化junit测试的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Boot MVC 测试中自定义 bean

Spring Boot中自定义注解

在 Spring Batch 应用程序中自定义步骤的参数

在 Spring Boot 中自定义异常返回空消息 [重复]

在 Spring Boot 中自定义 JSON 响应以更改键名

使用 IntelliJ 在 Spring Boot 中自定义应用程序属性