我有一个用Jersey& amp;编写的REST服务。弹簧引导。我为POST参数编写了自定义验证器类。我想对它进行单元测试。我无法弄清楚如何做到这一点。我的验证器如下所示:
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ValidTaskForCreate.Validator.class)
public @interface ValidTaskForCreate {
String message() default "Invalid Request to create a Task";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
public class Validator implements ConstraintValidator<ValidTaskForCreate, Task> {
@Override
public void initialize(ValidTaskForCreate constraintAnnotation) {
}
@Override
public boolean isValid(final Task task, ConstraintValidatorContext context) {
context.disableDefaultConstraintViolation();
if(task.getName() == null || task.getName().isEmpty()) {
context.buildConstraintViolationWithTemplate("Task name should be specified").addConstraintViolation();
return false;
}
if(task.getTaskType() == null) {
context.buildConstraintViolationWithTemplate("Specify a valid TaskType in the range of [1..3]").addConstraintViolation();
return false;
}
return true;
}
}
}
现在我想通过传递各种Task对象来测试isValid()函数。我不知道如何调用此方法。 我可以像这样创建Validator类的实例,
ValidTaskForCreate.Validator taskValidator = null;
taskValidator = new ValidTaskForCreate.Validator();
要调用isValid(),我可以使用taskValidator.isValid()。但我不知道如何创建ConstraintValidatorContext对象作为第二个参数传递。
或者是否有任何方法可以使用像这样的UnitTest自定义验证类?
答案 0 :(得分:2)
但我不知道如何创建ConstraintValidatorContext对象作为第二个参数传递。
只需使用Mockito并嘲笑它。然后只需验证是否调用了正确的方法。这是在涉及依赖性时测试单元行为的方法。
private ConstraintValidatorContext context;
private ConstraintValidatorContext.ConstraintViolationBuilder builder;
@Before
public void setup() {
// mock the context
context = Mockito.mock(ConstraintValidatorContext.class);
// context.buildConstraintViolationWithTemplate returns
// ConstraintValidatorContext.ConstraintViolationBuilder
// so we mock that too as you will be calling one of it's methods
builder = Mockito.mock(ConstraintValidatorContext.ConstraintViolationBuilder.class);
// when the context.buildConstraintViolationWithTemplate is called,
// the mock should return the builder.
Mockito.when(context.buildConstraintViolationWithTemplate(Mockito.anyString()))
.thenReturn(builder);
}
@Test
public void test() {
// call the unit to be tested
boolean result = ..isValid(badTask, context);
// assert the result
assertThat(result).isFalse();
// verify that the context is called with the correct argument
Mockito.verify(context)
.buildConstraintViolationWithTemplate("Task name should be specified");
}
请注意直接使用Mockito
。在大多数情况下,您可能只是使用静态导入来减少冗长。我只是想让它更具可读性
答案 1 :(得分:0)
这是我发现使用标准 Spring 单元测试的最佳方式,无需模拟任何内容。
@RunWith(SpringRunner.class)
@SpringBootTest(classes= {ValidationAutoConfiguration.class})
public class AllowedValuesValidatorTest {
@Autowired
private Validator validator;
@Test
public void testIsValid() {
ObjectToBeValidated obj = // create object
Set<ConstraintViolation<ObjectToBeValidated>> violations = validator.validate(obj);
boolean violationsFound =
violations.stream().anyMatch(v -> v.getConstraintDescriptor().getAnnotation().annotationType().equals(
NonNullLowercaseLettersOrNumbersOnly.class));
assertThat(externalIdViolationFound).isTrue();
}
}
ValidationAutoConfiguration.class 作为测试的配置完成了繁重的工作。这将在 ObjectToBeValidated 上执行所有验证,您可以搜索您正在测试的违规行为。