本周开始就正式开始上课了,虽然说这学期开头不怎么好,可是这学期的课都还挺不错的,学着颇有意思,在团队学习了这么长时间,再加上半年多没在教室学习,致使我对老师讲课的方式不是很适应,“万课皆理论”这种方式在我看来是不会教,可是在和团队的同窗讨论以后,发现是我片面了,毕竟对于大多数人来讲,学习的目的是拿高成绩,高绩点,而我想的是要学会怎么用,反正无论怎么样吧,都会好好学的。java
@Test void page() throws Exception { int page = new Random().nextInt(); Long courseId = new Random().nextLong(); Long modelId = new Random().nextLong(); Integer difficult = new Random().nextInt(); Subject subject = getOneSubject(); Subject subSubject = getOneSubject(); subject.setSubjects(Arrays.asList(subSubject)); Tag tag = TagControllerTest.getOneTag(); subject.setTags(Arrays.asList(tag)); List<Subject> subjects = new ArrayList<>(); subjects.add(subject); Page<Subject> subjectPage = new PageImpl(subjects); Mockito.doReturn(subjectPage).when(this.subjectService).page(Mockito.any(), Mockito.any(Long.class), Mockito.any(Long.class), Mockito.any(Integer.class), Mockito.any()); String url = baseUrl; this.mockMvc.perform(MockMvcRequestBuilders.get(url) .param("page", String.valueOf(page)) .param("collegeId", courseId.toString()) .param("modelId", modelId.toString()) .param("difficult", difficult.toString()) .param("tags", Arrays.asList(tag).toString())) .andDo(MockMvcResultHandlers.print()) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].id").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].mark").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].stem").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].analysis").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].createTime").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].difficult").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].used").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].course").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].course.name").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].model").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].options.length()").value(1)) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].options[0].id").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].options[0].content").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].subjects.length()").value(1)) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].subjects[0].id").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].tags.length()").value(1)) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].tags[0].id").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.content[0].tags[0].name").exists()); }
以上是对page()方法进行的单元测试,而后看一下报错:git
java.lang.AssertionError: No value at JSON path "$.content[0].id"
还记得上周凯强在汇报中提到了没有JSON字符Value的问题,而后打印一下JSON字符串看一下具体问题:
在回应中Body属性为空,什么都没返回,而后在凯强的指导下把参数传输所有改成Mockito.any(),而后:github
Mockito.doReturn(subjectPage).when(this.subjectService).page(Mockito.any(), Mockito.any(),Mockito.any(), Mockito.any(), Mockito.any());
通过排查发现是参数名定义错了,courseId定义成了collegeId,可是由此引起疑问,为什么定义Mockito.any()就不报错,而定义Mockito.any(Long.class)就会出现问题呢,咱们再对另外一个变量进行测试,将modelId 传为 model:json
@Test void page() throws Exception { int page = new Random().nextInt(); Long courseId = new Random().nextLong(); Long modelId = new Random().nextLong(); Integer difficult = new Random().nextInt(); Subject subject = getOneSubject(); Subject subSubject = getOneSubject(); subject.setSubjects(Arrays.asList(subSubject)); Tag tag = TagControllerTest.getOneTag(); subject.setTags(Arrays.asList(tag)); List<Subject> subjects = new ArrayList<>(); subjects.add(subject); Page<Subject> subjectPage = new PageImpl(subjects); Mockito.doReturn(subjectPage).when(this.subjectService).page(Mockito.any(), Mockito.any(Long.class), Mockito.any(Long.class), Mockito.any(Integer.class), Mockito.any()); String url = baseUrl; this.mockMvc.perform(MockMvcRequestBuilders.get(url) .param("page", String.valueOf(page)) .param("courseId", courseId.toString()) .param("model", modelId.toString()) .param("difficult", difficult.toString()) .param("tags", Arrays.asList(tag).toString())) .andDo(MockMvcResultHandlers.print()) .andExpect(MockMvcResultMatchers.status().isOk()); }
而后就会出现一样的错误,Response里面的Body属性没有值,可是若是更改成Mockito.any()就能经过测试了。
因此说以前的问题并不是个例,而是广泛存在的,若是使用Mockito.any()就会致使测试不严谨,字段不对应也不能知道,而使用Mockito.any(<T>.class)就要严格对应,就能发现问题,至于为啥会出现这种问题还没搞明白,多是SpringBoot测试的一种机制吧。segmentfault
在通过潘老师讲解,因为接收的是collegeId,那么courseId接受的值为null,null不是Long类型,没法匹配,就不认为是原来的page方法,可是换为any()就能正常匹配,而后就能经过测试了。dom
随着对单元测试接触的愈来愈多,暴露的问题也愈来愈多,注意的要点也愈来愈多,发现单元测试也没有以前想的那么难了。
千淘万漉虽辛苦,吹尽狂沙始到金。单元测试
本文做者:河北工业大学梦云智开发团队 张文达学习