共计 4301 个字符,预计需要花费 11 分钟才能阅读完成。
前言
本周开始就正式开始上课了,虽说这学期结尾不怎么好,然而这学期的课都还挺不错的,学着很有意思,在团队学习了这么长时间,再加上半年多没在教室学习,导致我对老师讲课的形式不是很适应,“万课皆实践”这种形式在我看来是不会教,然而在和团队的同学探讨之后,发现是我全面了,毕竟对于大多数人来说,学习的目标是拿高问题,高绩点,而我想的是要学会怎么用,反正不论怎么样吧,都会好好学的。
问题
@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() 办法进行的单元测试,而后看一下报错:
java.lang.AssertionError: No value at JSON path "$.content[0].id"
解决
还记得上周凯强在汇报中提到了没有 JSON 字符 Value 的问题,而后打印一下 JSON 字符串看一下具体问题:
在回应中 Body 属性为空,什么都没返回,而后在凯强的领导下把参数传输全副改为 Mockito.any(),而后:
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:
@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 测试的一种机制吧。
结语
随着对单元测试接触的越来越多,裸露的问题也越来越多,留神的要点也越来越多,发现单元测试也没有之前想的那么难了。
千淘万漉虽辛苦,吹尽狂沙始到金。
本文作者:河北工业大学梦云智开发团队 张文达