問題描述
- 需要為某個controller寫一個單元測試,使用MockMvc進行測試
- 還是使用@Autowired注入一個MockMvc的對象,使用@MockBean給service注入一個Mock對象
- @RunWith(SpringRunner.class)運行測試
- 但是測試一運行就會報錯,爆出can not create
ComputeControllerTest bean
- 還記得之前springBoot的單元測試我就采用了這樣的方式測試也沒有出錯
@RunWith(SpringRunner.class)
public class ComputeControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private ComputeService computeService;
@Test
public void should_return_sum_answer() throws Exception {
.....
}
}
問題分析
- Q1:認真分析錯誤log中
Caused by:No qualifying bean of type 'org.springframework.test.web.servlet.MockMvc' available
- A1:說明沒有辦法為
ComputeControllerTest
創(chuàng)建一個Bean原因:ComputeControllerTest的bean依賴于MockMvc和ComputeService的bean都創(chuàng)建成功,而且錯誤說是MockMvc無法創(chuàng)建Bean
- Q2:為什么MockMvc沒有辦法創(chuàng)建bean?
- A2:首先MockMvc不是由我們自己創(chuàng)建的,沒有辦法采用@Bean的方式強制其創(chuàng)建,所以必然是spring的ApplicationContext沒有加載全,那么一般spring會通過注解自動將所需的上下文引入
- Q3:那么使用什么樣的注解能夠將帶有MockMvc Bean的上下文加載進來呢?
- 那么此時分析原因后就應該去官網找demo看看人家是什么寫的
- Q4:發(fā)現自己在test類之前少了
@WebMvcTest()
注解,因此我飛快的填上寫成如下形式,仍然爆出 一樣的錯誤,為什么官網這樣寫就能run?
@RunWith(SpringRunner.class)
@WebMvcTest(Application.class)
public class ComputeControllerTest {
.....
}
- A4:認真和demo比對后,我發(fā)現了自己寫錯了@WebMvcTest()的參數,將參數改成ComputeController.class就沒有爆出同樣的錯誤了
- Q5.卻發(fā)現測試還是掛著的,我在測試中使用了assertJ的mock,
given(computeService.compute(1,2)).willReturn(3);
發(fā)現報錯說given的參數不是一個Mock對象,明明我是通過@MockBean的注解注入的值為什么不是Mock對象?
- A5:還記得以前提起過,集成測試沒有辦法Mock是因為所有的服務都被啟動了,真正需要向服務器發(fā)請求,所以服務內部我們就不可控,更沒有辦法將服務內的某個東西使用Mock對象代替。因此由這樣遷移就可以發(fā)現必然是service還是并沒有被mock對象頂替,到了service中發(fā)現Service中的compute竟然成了靜態(tài)方法,修改之后,測試通過
解答思考
- @WebMvcTest(Application.class)注解有什么作用,參數又代表了什么?
- @WebMvcTest(Application.class):自動加載spring Mvc的配置、MockMvc的配置,掃描注解類,其實簡單的說就是,這個注解提供了MockMvc的Bean所需要的Bean
- @WebMvcTest(Application.class)參數的作用:通常是MockMvc做單元測試,并且他只會啟動部分的服務,而不是整個服務器。這句話我一直不能理解,直到了解了這個參數,參數是一個你需要測試的Controller類,也就是說,這個注解只會啟動參數controller的那一部分服務,也就是所謂部分的服務,因此我之前填寫的整個Application.class就不會起作用。
- 我猜想,因為靜態(tài)方法不需要實例也就是說調用這個方法的不要求對應類有個實例,換句話說,不需要對應類的Bean就可以直接使用這個方法。然而當你Mock掉一個類的時候,就是通過使用Mock的bean替換真實的bean。然而靜態(tài)方法不需要bean,所以這個方法自然跟mock對象沒有任何關系。就更不可能控制它的返回值
想說的話
- 現在看英文文檔已經沒有那么拒絕了,但是還是有個很大的問題就是漏掉重點!!!這個該怎么辦······哎先多看看吧
- 發(fā)現自己想當然的本事很厲害,以前那些注解能用絕對不查,總是自以為他是這個作用,必然導致下次不會用,再出bug,這個問題我很矛盾,雖然我應該查清楚我不會的部分到底是什么作用,可又會花費我很多時間。。這又該怎么辦
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。