简体   繁体   中英

How to ignore a validation / ConstraintValidator in a webservice junit test?

I have the following simple webservice that requires a LocalDate in future. The annotation is a custom one, as follows:

@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = DateInFutureValidator.class)
public @interface DateInFuture {
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

public class DateInFutureValidator implements ConstraintValidator<DateInFuture, Temporal> {
    @Override
    public void initialize(DateInFuture constraintAnnotation) { }

    @Override
    public boolean isValid(Temporal value, ConstraintValidatorContext context) {
        //validation logic
    }
}

Question: how can I disable that annotation during a junit integration test (that uses a date that will be in the past in a while)?

The spring servlet:

@RestController
public class MyController {
    @PostMapping(path)
    public Rsp post(MyDTO dto) {

    }
}


public class MyDTO {
    @NotNull
    @DateInFuture
    private LocalDate date;
}

The ITest:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SpringItest {

    @Autowired
    protected MockMvc mvc;

    @Test
    public void springItest() {
        mvc.perform(MockMvcRequestBuilders
                .post(path)
                .contentType(MediaType.APPLICATION_JSON)
                .content(requestAsJson)
                .andExpect(status().isOk());
    }
}

As @membersound has already mentioned that the DateInFutureValidator is not part of the project, so he needn't test the DateInFutureValidator at all. so we can just disable it by use the trick of ClassLoader how to load classes.

When there is a class with full qualified name as library class in the test source directory, the ClassLoader will load it and ignore the library class.

package ${package_name_same_as_library_class};

public class DateInFutureValidator implements ConstraintValidator<DateInFuture, Temporal> {
  @Override
  public void initialize(DateInFuture constraintAnnotation) { }

  @Override
  public boolean isValid(Temporal value, ConstraintValidatorContext context) {
    return true;
  }
}

The downside of this approach is it will disable DateInFutureValidator globally. but it doesn't matter in this case since it run in integration test only.

You can do this with a standalone setup of a MockMvc instance by providing a mock validator which will prevent it from performing any validation.

Validator mockValidator = mock(Validator.class);

MockMvc mockMvc = MockMvcBuilder.standaloneSetup(myController).setValidator(mockValidator);

If you want to do a web application set up of your MockMvc, which is the case with the auto configured MockMvc instance you are currently using then I think you should be able to provide a mock Validator to the whole context by just declairing a @MockBean Validator:

@MockBean(name = "mvcValidator")
private Validator mockValidator;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM