gpt4 book ai didi

javax.validation.ValidationException : HV000028: Unexpected exception during isValid in Test

转载 作者:行者123 更新时间:2023-12-02 09:00:05 34 4
gpt4 key购买 nike

我不知道如何为自定义约束 validator 编写单元测试。我有以下 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 是一个使用 ApiClient 调用 School Api 的类,ApiClient 是一个具有通用 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");
}
}
}

最后是学生类:

@Data
public class Student {

private String id;
private String firstName;
private String lastName;
@ValidSchoolId
private String schoolId;
}

当我运行该应用程序时,它运行良好。但是,它根本不适用于以下测试类:

@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。因此,它总是在 SchoolIdValidator.isValid 上抛出 NPE。如果有人有解决方案,那将非常有帮助。

感谢您的阅读和帮助。

最佳答案

这里的@InjectMocks可能就是问题所在。

@RunWith(MockitoJUnitRunner.class)
@ExtendWith(SpringExtension.class)
public class SchoolIdValidatorTest {

Validator validator;

@InjectMocks
private SchoolService schoolService;

连同

Validation.buildDefaultValidatorFactory().getValidator()

我假设 SchoolService 通常是一个 Spring 托管 bean,并且 SchoolIdValidator 会将其注入(inject)。通过使用 @InjectMocks ,您可以说这不是 Spring 托管 bean。此类由 Mockito 实例化,因此它永远不会被注入(inject)到您的 validator 中。

我不确定这里的正确解决方案是什么,因为您没有发布任何配置类。最有可能的是,您需要一个额外的测试配置类来实例化您的 validator ApiClient 并注入(inject)您的 SchoolService。您还可以使用 @MockBean 模拟 ApiClient,这将使其成为 Spring 托管 bean,但也允许模拟。

有点相关,这里确实有构造函数。没有理由使用@InjectMocks。只需使用 new SchoolService(apiSchoolClient) 即可。

关于javax.validation.ValidationException : HV000028: Unexpected exception during isValid in Test,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60229517/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com