Я не могу понять, как написать модульный тест для пользовательского средства проверки ограничений. У меня есть следующий класс Validator:
@Slf4j
@AllArgsConstructor
@NoArgsConstructor
public class SchoolIdValidator implements ConstraintValidator<ValidSchoolId, String> {
private SchoolService schoolService;
@Override
public void initialize(ValidSchoolId constraintAnnotation) {}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
return schoolService.isValidSchoolId(s);
}
}
Validator используется следующей аннотацией:
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = SchoolIdValidator.class)
public @interface ValidSchoolId {
String message() default "Must be a valid school. Found: ${validatedValue}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
SchoolService
- это класс, который вызывает Api School с использованием ApiClient, который класс Generi c с Generi c restTemplate запросов:
@Service
@AllArgsConstructor
public class SchoolService {
private ApiClient apiSchoolClient;
public Boolean isValidSchoolId(String schoolId){
try {
ResponseEntity res = apiSchoolClient.get(
String.format("/stores/%s", schoolId), Object.class, null);
return res.getStatusCode().is2xxSuccessful();
} catch (HttpClientErrorException e) {
if(e.getStatusCode().value() == 404)
return false;
else
throw new TechnicalException("Can't get response from school Api");
} catch(RestClientException e) {
throw new TechnicalException("Can't get response from School Api");
}
}
}
И, наконец, класс Student:
@Data
public class Student {
private String id;
private String firstName;
private String lastName;
@ValidSchoolId
private String schoolId;
}
Когда я запускаю приложение, оно работает отлично. Но он совсем не работает со следующим классом Test:
@RunWith(MockitoJUnitRunner.class)
@ExtendWith(SpringExtension.class)
public class SchoolIdValidatorTest {
Validator validator;
@InjectMocks
private SchoolService schoolService;
@Mock
private ApiClient apiSchoolClient;
@Before
public void setUp() throws Exception {
validator = Validation.buildDefaultValidatorFactory().getValidator();
MockitoAnnotations.initMocks(this);
}
@Test
public void isValid_SchoolIdExists_ShouldValidate() {
Mockito.when(this.apiSchoolClient.get(Mockito.eq("/schools/12"), Mockito.any(), Mockito.any()))
.thenReturn(new ResponseEntity<>(HttpStatus.OK));
//given
Student student = new Student();
simulation.setSchoolId("12");
//when
Set<ConstraintViolation<Student>> violations = validator.validate(student);
//then
assertEquals(0, violations.size());
}
Когда он входит, SchoolIdValidator
schoolService
всегда null
. Таким образом, он всегда выбрасывает NPE на SchoolIdValidator.isValid. Если у кого-то есть решение, оно будет очень полезно.
Спасибо за чтение и вашу помощь.