带有@RequestParam 和状态的@Controller 的WebMvcTest 不是200,而是400
WebMvcTest of @Controller with @RequestParam and status is not 200, but 400
我试着写@WebMvcTest:
@ExtendWith(SpringExtension.class)
@WebMvcTest(AudienceController.class)
class LectureControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private LectureService lectureService;
@MockBean
private GroupService groupService;
@MockBean
private TeacherService teacherService;
@MockBean
private StudentService studentService;
@BeforeEach
public void init() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new LectureController(lectureService, groupService, teacherService, studentService)).build();
}
@Test
void whenGetRequest_thenReturnTTForTeacherPage() throws Exception {
Teacher teacher = new Teacher(1, "teacher", "first");
Subject subject = new Subject(1, "first");
LocalDateTime date = LocalDateTime.now();
Audience audience = new Audience(1, 100);
Group group = new Group(1, "group");
Lecture lecture = new Lecture(1, teacher, subject, Arrays.asList(group), date);
lecture.setAudience(audience);
when(teacherService.findOne(1)).thenReturn(teacher);
when(lectureService.findLecturesByTeacher(teacher, date, date)).thenReturn(Arrays.asList(lecture));
mockMvc.perform(get("/lecture/TTForTeacher/{id}", 1)
.param("startDay", date.toString())
.param("endDay", date.toString()))
.andDo(print())
.andExpect(status().isOk())
.andExpect(view().name("lecture/TTForTeacher"))
.andExpect(forwardedUrl("lecture/TTForTeacher"))
.andExpect(model().attribute("lectures", hasSize(1)))
.andExpect(model().attribute("lectures", hasItem(
allOf(
hasProperty("id", is(1)),
hasProperty("teacher", is(teacher)),
hasProperty("subject", is(subject)),
hasProperty("date", is(date)),
hasProperty("audience", is(audience)),
hasProperty("groups", is(Arrays.asList(group)))
)
)));
verify(lectureService, times(1)).findLecturesByTeacher(teacher, date, date);
}
我的控制器:
@Controller
@RequestMapping("/lecture")
public class LectureController {
private LectureService lectureService;
private GroupService groupService;
private TeacherService teacherService;
private StudentService studentService;
public LectureController(LectureService lectureService, GroupService groupService, TeacherService teacherService,
StudentService studentService) {
this.lectureService = lectureService;
this.groupService = groupService;
this.teacherService = teacherService;
this.studentService = studentService;
}
@GetMapping("/TTForTeacher/{id}")
public String getTTForTeacher(@PathVariable("id") int id, @RequestParam(value = "startDay") LocalDateTime startDay,
@RequestParam(value = "endDay") LocalDateTime endDay, Model model) {
model.addAttribute("lectures",
lectureService.findLecturesByTeacher(teacherService.findOne(id), startDay, endDay));
return "lecture/TTForTeacher";
}
但它有失败:"Status expected:<200> but was:<400>"
这在控制台中:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /lecture/TTForTeacher/1
Parameters = {startDay=[10.05.2020, 10:00], endDay=[31.05.2020, 20:00]}
Headers = []
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.foxminded.university.controller.LectureController
Method = com.foxminded.university.controller.LectureController#getTTForTeacher(int, LocalDateTime, LocalDateTime, Model)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.method.annotation.MethodArgumentTypeMismatchException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
我试过不使用.param("day", date.toString), 给这个参数设置多种格式的字符串,不使用.param,但是我有这个异常,你能帮忙吗我和它。其他方法的所有其他测试都成功,但这些方法中没有@RequestParam。那么我如何测试这样的方法
控制器缺少解析数据的逻辑。 Spring 默认情况下不知道如何将字符串转换为日期时间对象。有两种方法可以解决这个问题,一种解决方案可以将日期读取为字符串而不是 LocalDate,然后解析字符串以获取开始日期和结束日期,但是使用 @DateTimeFormat https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/format/annotation/DateTimeFormat.html
有更好的方法
控制器方法变成这样
public String getTTForTeacher(@PathVariable("id") int id, @RequestParam(value = "startDay") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDay,
@RequestParam(value = "endDay") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDay) {
测试 mockMvc 可以保留原样,因为您正在做 LocalDateTime.now().toString()
我试着写@WebMvcTest:
@ExtendWith(SpringExtension.class)
@WebMvcTest(AudienceController.class)
class LectureControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private LectureService lectureService;
@MockBean
private GroupService groupService;
@MockBean
private TeacherService teacherService;
@MockBean
private StudentService studentService;
@BeforeEach
public void init() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new LectureController(lectureService, groupService, teacherService, studentService)).build();
}
@Test
void whenGetRequest_thenReturnTTForTeacherPage() throws Exception {
Teacher teacher = new Teacher(1, "teacher", "first");
Subject subject = new Subject(1, "first");
LocalDateTime date = LocalDateTime.now();
Audience audience = new Audience(1, 100);
Group group = new Group(1, "group");
Lecture lecture = new Lecture(1, teacher, subject, Arrays.asList(group), date);
lecture.setAudience(audience);
when(teacherService.findOne(1)).thenReturn(teacher);
when(lectureService.findLecturesByTeacher(teacher, date, date)).thenReturn(Arrays.asList(lecture));
mockMvc.perform(get("/lecture/TTForTeacher/{id}", 1)
.param("startDay", date.toString())
.param("endDay", date.toString()))
.andDo(print())
.andExpect(status().isOk())
.andExpect(view().name("lecture/TTForTeacher"))
.andExpect(forwardedUrl("lecture/TTForTeacher"))
.andExpect(model().attribute("lectures", hasSize(1)))
.andExpect(model().attribute("lectures", hasItem(
allOf(
hasProperty("id", is(1)),
hasProperty("teacher", is(teacher)),
hasProperty("subject", is(subject)),
hasProperty("date", is(date)),
hasProperty("audience", is(audience)),
hasProperty("groups", is(Arrays.asList(group)))
)
)));
verify(lectureService, times(1)).findLecturesByTeacher(teacher, date, date);
}
我的控制器:
@Controller
@RequestMapping("/lecture")
public class LectureController {
private LectureService lectureService;
private GroupService groupService;
private TeacherService teacherService;
private StudentService studentService;
public LectureController(LectureService lectureService, GroupService groupService, TeacherService teacherService,
StudentService studentService) {
this.lectureService = lectureService;
this.groupService = groupService;
this.teacherService = teacherService;
this.studentService = studentService;
}
@GetMapping("/TTForTeacher/{id}")
public String getTTForTeacher(@PathVariable("id") int id, @RequestParam(value = "startDay") LocalDateTime startDay,
@RequestParam(value = "endDay") LocalDateTime endDay, Model model) {
model.addAttribute("lectures",
lectureService.findLecturesByTeacher(teacherService.findOne(id), startDay, endDay));
return "lecture/TTForTeacher";
}
但它有失败:"Status expected:<200> but was:<400>" 这在控制台中:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /lecture/TTForTeacher/1
Parameters = {startDay=[10.05.2020, 10:00], endDay=[31.05.2020, 20:00]}
Headers = []
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.foxminded.university.controller.LectureController
Method = com.foxminded.university.controller.LectureController#getTTForTeacher(int, LocalDateTime, LocalDateTime, Model)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.method.annotation.MethodArgumentTypeMismatchException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
我试过不使用.param("day", date.toString), 给这个参数设置多种格式的字符串,不使用.param,但是我有这个异常,你能帮忙吗我和它。其他方法的所有其他测试都成功,但这些方法中没有@RequestParam。那么我如何测试这样的方法
控制器缺少解析数据的逻辑。 Spring 默认情况下不知道如何将字符串转换为日期时间对象。有两种方法可以解决这个问题,一种解决方案可以将日期读取为字符串而不是 LocalDate,然后解析字符串以获取开始日期和结束日期,但是使用 @DateTimeFormat https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/format/annotation/DateTimeFormat.html
有更好的方法控制器方法变成这样
public String getTTForTeacher(@PathVariable("id") int id, @RequestParam(value = "startDay") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDay,
@RequestParam(value = "endDay") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDay) {
测试 mockMvc 可以保留原样,因为您正在做 LocalDateTime.now().toString()