spring-boot - Spring Boot Validation:如何测试 DTO 对象
问题描述
我有StudentController
我必须测试的方法。我想测试StudentDTO
验证:
@PostMapping("successStudentAddition")
public String addStudent(@ModelAttribute("student") @Validated StudentDTO studentDTO, Errors errors, Model model) {
if (errors.hasErrors()) {
model.addAttribute(STUDENT_MODEL, studentDTO);
return "/studentViews/addStudent";
}
Student student = new Student(studentDTO.getStudentId(), studentDTO.getStudentName(), studentDTO.getStudentSurname(),
studentDTO.getStudentAge(), studentDTO.getEntryYear(), studentDTO.getGraduateYear(), studentDTO.getFacultyName(),
groupService.getGroupIdByName(studentDTO.getGroupName()));
studentService.addStudent(student);
return "/studentViews/successStudentAddition";
}
StudentDTO.class
:
public class StudentDTO {
@Id
private int studentId;
@NotNull
@Size(min=2,max=30,message = "Name should consist of 2 to 30 symbols!")
private String studentName;
@NotNull
@Size(min = 2, max = 30,message = "Surname should consist of 2 to 30 symbols!")
private String studentSurname;
@NotNull
@Min(value = 10,message = "Student age should be more than 10!")
private int studentAge;
@NotNull
@Min(value = 1900,message = "Entry year should be more than 1900!")
@Max(value=2021,message = "Entry year should be less than 2021!")
private int entryYear;
@NotNull
@Min(value = 2020,message = "Graduate year should be not less than 2020!")
private int graduateYear;
@NotNull
@Size(min = 3,message = "Faculty name should consist of minimum 3 symbols!")
private String facultyName;
@NotNull
@Size(min = 4,message = "Group name should consist of 4 symbols!")
@Size(max = 4)
private String groupName;
}
我找到了一些测试的想法:
@ExtendWith(SpringExtension.class)
@SpringBootTest
class ValidatingServiceWithGroupsTest {
@Autowired
private ValidatingServiceWithGroups service;
@Test
void whenInputIsInvalidForCreate_thenThrowsException() {
InputWithGroups input = validInput();
input.setId(42L);
assertThrows(ConstraintViolationException.class, () -> {
service.validateForCreate(input);
});
}
@Test
void whenInputIsInvalidForUpdate_thenThrowsException() {
InputWithGroups input = validInput();
input.setId(null);
assertThrows(ConstraintViolationException.class, () -> {
service.validateForUpdate(input);
});
}
}
但。如果在上面的代码中我们在没有任何输入参数的情况下测试服务,我应该使用这样的参数给控制器:Errors errors
和Model model
。我有麻烦。
添加 test 后的所有堆栈跟踪:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'studentController': Unsatisfied dependency expressed through field 'studentService'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.foxminded.springboot.service.StudentService' available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.foxminded.springboot.service.StudentService' available: expected at least 1 bean which qualifies as
autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
解决方案
根据您在问题中提供的内容,我了解您需要测试StudentDTO
dto 类的验证。dto 类的验证将在 spring 自动绑定时触发。因此,要测试此验证,您只需使用将触发验证并检查响应的 json 正确调用控制器方法。如果验证失败,它将触发MethodArgumentNotValidException
. 默认情况下,Spring 会将此异常转换为 HTTP 状态 400(错误请求)。
@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = StudentController.class)
class StudentControllerTest {
@Autowired
private MockMvc mvc;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private StudentService service;
@Test
void whenInputIsInvalid_thenReturnsStatus400() throws Exception {
Input input = invalidInput();
String body = objectMapper.writeValueAsString(input);
mvc.perform(post("/successStudentAddition")
.content(body))
.andExpect(status().isBadRequest());
}
}
但是在您的情况下,发生错误时您将返回不同的视图,因此您需要对此进行测试。因此,在您的情况下测试响应,例如:
this.mockMvc.perform(post("/successStudentAddition")
.accept(MediaType.TEXT_HTML))
.andExpect(status().isOk())
.andExpect(model().attribute("yourmodel", "assertIt"))
.andDo(print());
推荐阅读
- javascript - 如何使用 PHP ajax 在模态框中提交 HTML 表单数据?
- python - Matplotlib - 如何从任何条形的顶部到 y 轴画一条线?
- php - 将变量从控制器传递到视图时,Codeigniter form_open() 加载视图文件两次
- python - 如何在 Django 中从 MultiValueDict 读取或保存文件
- python - 如何使用 numpy 加载读取 zip 文件中的 npz 文件
- java - 判断api请求是来自CURL还是POSTMAN?
- jquery - 使用 Jquery 在单击时选择列表中的下一个元素
- python - 在 Python 中绘制有向图?
- javascript - 如何为 vanilla-lazyload 动态设置图像高度和宽度
- node.js - Mongoose findByIdAndUpdate 销毁缺失的字段