Spring Boot單元測試(Mock)
Mock
單元測試的重要性就不多說了,我這邊的工程一般都是Spring Boot+Mybatis(詳情可參看《Spring boot+MyBatis+PageHelper+JSON》),現在寫一下Spring Boot下怎么測試Controller、Service。
Controller測試
本文就簡單一點,寫一個Hello接口。
Controller
HTTP請求測試:
既然是測試Controller接口,肯定就是發送HTTP請求了,之前的文章我也有提到,可以使用Postman、Swagger進行測試,本文我們采用編碼的方式測試,新建HttpRequestTest類:
HTTP測試類
注意三個紅框,這是告訴Spring Boot啟動的時候采用一個隨機的端口,有助於在測試環境中避免沖突(官網解釋)。
綠框的restTemplate,看過之前我的《Spring Cloud網關與負載均衡Zuul與Ribbon》就知道,與RestTemplate差不多,這就是個HTTP客戶端。
運行測試通過。注意看日志,會找到一行日志:
Tomcat started on port(s):XXXXX
這說明整個Tomcat已經啟動成功了。
MockMVC測試:
注意上面的測試,通過日志我們知道,其實就是啟動了Tomcat,然后通過TestRestTemplate構建了HTTP請求。但是在我們實際開發中,有一個現實的問題,我們一個工程會有很多的Controller、Service、Mapper,但是我們本次測試可能就測一個接口。為了一個接口,要啟動整個Tomcat,太浪費了。所以我們可以采用MockMVC,在不啟動的服務的情況下,測試接口:
Mock測試
實際開發中,肯定會有很多Controller,紅框內我們指定本次測試只實例化HellController這一個。
另外在開發的時候,Eclipse沒法通過快捷鍵進行import static,所以我們要手工導入以下:
導入
運行本測試,注意看日志,就不會出現Tomcat started on port(s):XXXXX的記錄了。
Service測試
在實際開發中,Service的邏輯處理比較多,應該是最先被測試的,本示例增加一個Service和Mapper,如下:
Mapper
在我之前那個完整的工程中,這個注解應該是@Mapper,本例我沒引入數據庫,只是模擬一下,所以用了@Repository。
Service
在@Service下應該還有事務注解@Transactional,本例只是模擬,所以也沒有加。
測試類如下:
測試類
注意紅框,在實際開發中,我們自己寫的Controller、Service很可能去調用別的同事或別的項目組寫的Service、Mapper,對方可能只寫了一個接口,沒有實現(比如本例中我寫的Mapper),這樣是沒法進行測試的。
Mock的作用就是創建一個虛擬的對象替代那些不易構造或不易獲取的對象。
本例中我都沒有引入數據庫的相關依賴,本來應該是連接數據庫的Mapper,現在就是一個單純的接口,如果不對Mapper進行處理,這個測試就沒法進行下去。
於是在第一個紅框內Mock了一個HelloMapper,第二個紅框對這個Mock對象的方法進行了處理,等於Mapper接收參數“leo”,返回結果“Hello leo”,給Service使用。
運行測試通過。
Controller測試(含Service)
在“MockMVC測試”一節中,我們只測了Controller里的一個方法,沒有引入Service,這在實際工作中是不可能的,我們要么引入自己寫的Service,要么引入其他同事寫的Service(接口形式),如果這時候引入的Service同樣沒有實現,這測試也沒法做下去。結合“Service測試”的內容,我們可以這么做:
Controller
Controller新增一個方法,調用了Service。
測試類
測試類增加如上代碼,Mock一個假的Service,用when來處理Service,用MockMVC模擬HTTP請求,測試通過。