【发布时间】:2019-10-19 04:34:58
【问题描述】:
我目前正在提供覆盖 - 通过 MockMVC 请求调用测试我的 DTO 的验证。 我最近在我的注册约束验证器中引入了一个新字段,supportedSpecializations,我从 application.properties 中注入了值,以便于维护和扩展。请参阅下面的代码片段:
@Component
public class RegistrationValidator implements ConstraintValidator<Registration, String> {
//campus.students.supportedspecializations="J2E,.NET,OracleDB,MySQL,Angular"
@Value("${campus.students.supportedspecializations}")
private String supportedSpecializations;
private String specializationExceptionMessage;
//All ExceptionMessages are maintained in a separate class
@Override
public void initialize(Registration constraintAnnotation) {
exceptionMessage = constraintAnnotation.regionException().getMessage();
}
@Override
public boolean isValid(RegistrationData regData, ConstraintValidatorContext context) {
String[] specializations = supportedSpecializations.split(",");
boolean isValidSpecialization = Arrays.stream(specializations)
.anyMatch(spec -> spec.equalsIgnoreCase(regData.getSpec()));
if (!isValidSpecialization){
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(specializationExceptionMessage)
.addConstraintViolation();
return false;
}
//additional validation logic...
return true;
}
}
单元测试现在由于@Value 注释的定义属性未注入该字段而失败。 我不确定 ReflectionTestUtils 是否对我的情况有所帮助,因此非常感谢任何有关如何在 UnitTests 中注入所需值的建议。
Spring 版本是 2.1.0 我目前正在使用以下 sn-p 进行测试:
@InjectMocks
private StudentController mockRestController;
@Mock
private StudentService mockStudentService;
@Mock
private ValidationExceptionTranslator mockExceptionTranslator;
@Value("${campus.students.supportedspecializations}")
private String supportedSpecializations;
private MockMvc mockMvc;
private static final String VALIDATION_SUCCESSFUL = "success";
private static final String VALIDATION_FAILED = "failed";
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(mockRestController).build();
doReturn(
ResponseEntity.status(HttpStatus.OK)
.header("Content-Type", "text/html; charset=utf-8")
.body(VALIDATION_SUCCESSFUL))
.when(mockStudentService).insertStudent(Mockito.any());
doReturn(
ResponseEntity.status(HttpStatus.BAD_REQUEST)
.header("Content-Type", "application/json")
.body(VALIDATION_FAILED))
.when(mockExceptionTranslator).translate(Mockito.any());
}
@Test
public void testValidation_UnsupportedSpecialization() throws Exception {
MvcResult mvcResult = mockMvc.perform(
post("/Students").contentType(MediaType.APPLICATION_JSON_UTF8).content(
"{\"registrationData\":{\"spec\":\"unsupported\"}}"))
.andExpect(status().isBadRequest())
.andReturn();
assertEquals(VALIDATION_FAILED, mvcResult.getResponse().getContentAsString());
verify(mockExceptionTranslator, times(1)).translate(Mockito.any());
verify(mockStudentService, times(0)).insertStudent(Mockito.any());
}
我尝试使用 @RunWith(SpringRunner.class) 和 @SpringBootTest(classes = Application.class) 注释我的测试类,但验证测试仍然失败,原因是@Value 未解决。我可能错了,但我认为 ConstraintValidator 的实例是在我们到达 restController 之前创建的,所以 MockMVC perform(...) 调用不能简单地确保验证器中的适当 @Value 得到注入supportedSpecializations。
【问题讨论】:
-
你能发布你的单元测试吗?只是为了确定,但似乎您没有加载弹簧上下文,因此@Value 中没有注入任何值。
-
@XavierBouclet 我更新了帖子,请看一下
-
你在嘲笑你的控制器并嘲笑很多东西。默认情况下,Spring 不为处理约束验证器做任何事情。您将需要一个适当的
@WebMvcTest或完整的@SpringBootTest测试,否则@Value将无法解决。紧接着 Spring 并没有真正控制创建这些验证器的实例,而是验证器实现(在本例中为休眠),并且根据版本,Spirng 甚至不会处理该类。
标签: spring-boot spring-boot-test spring-framework-beans javax.validation