本週開始就正式開始上課了,雖然說這學期開頭不怎麼好,可是這學期的課都還挺不錯的,學着頗有意思,在團隊學習了這麼長時間,再加上半年多沒在教室學習,致使我對老師講課的方式不是很適應,「萬課皆理論」這種方式在我看來是不會教,可是在和團隊的同窗討論以後,發現是我片面了,畢竟對於大多數人來講,學習的目的是拿高成績,高績點,而我想的是要學會怎麼用,反正無論怎麼樣吧,都會好好學的。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
隨着對單元測試接觸的愈來愈多,暴露的問題也愈來愈多,注意的要點也愈來愈多,發現單元測試也沒有以前想的那麼難了。
千淘萬漉雖辛苦,吹盡狂沙始到金。單元測試
本文做者:河北工業大學夢雲智開發團隊 張文達學習