Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jersey custom validators unittest

I have a REST service written with Jersey & Spring-Boot. I have written custom validator classes for POST params. I want to unittest the same. I could not figure out how to do it. My Validator looks like below:

@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;
        }

    }
}

Now i want to test the isValid() function by passing various Task objects. I am not sure how to call this method now. I can create instance of Validator class like this,

    ValidTaskForCreate.Validator taskValidator = null;
    taskValidator = new ValidTaskForCreate.Validator();

To call isValid(), i can use taskValidator.isValid(). But i do not know how to create the ConstraintValidatorContext object to pass as 2nd parameter.

Or is there any way to UnitTest custom validations classes like this?

like image 460
Chenbaga Murugan Avatar asked Feb 08 '17 04:02

Chenbaga Murugan


1 Answers

But i do not know how to create the ConstraintValidatorContext object to pass as 2nd parameter.

Just use Mockito and mock it. Then just verify that the correct methods were called. This is how to test the behavior of the unit when dependencies are involved.

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");
}

Note the use of Mockito directly. In most cases you will probably just use static imports to make it less verbose. I just wanted to make it more readable

like image 192
Paul Samsotha Avatar answered Oct 21 '22 14:10

Paul Samsotha