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