天天看點

Spring Boot應用的測試——Mockito

spring boot可以和大部分流行的測試架構協同工作:通過spring junit建立單元測試;生成測試資料初始化資料庫用于測試;spring boot可以跟bdd(behavier driven development)工具、cucumber和spock協同工作,對應用程式進行測試。

進行軟體開發的時候,我們會寫很多代碼,不過,再過六個月(甚至一年以上)你知道自己的代碼怎麼運作麼?通過測試(單元測試、內建測試、接口測試)可以保證系統的可維護性,當我們修改了某些代碼時,通過回歸測試可以檢查是否引入了新的bug。總得來說,測試讓系統不再是一個黑盒子,讓開發人員确認系統可用。

在web應用程式中,對controller層的測試一般有兩種方法:(1)發送http請求;(2)模拟http請求對象。第一種方法需要配置回歸環境,通過修改代碼統計的政策來計算覆寫率;第二種方法是比較正規的思路,但是在我目前經曆過的項目中用得不多,今天總結下如何用mock對象測試controller層的代碼。

在之前的幾篇文章中,我們都使用bookpub這個應用程式作為例子,今天也不例外,準備測試它提供的restful接口是否能傳回正确的響應資料。這種測試不同于單元測試,需要為之初始化完整的應用程式上下文、所有的spring bean都織入以及資料庫中需要有測試資料,一般來說這種測試稱之為內建測試或者接口測試。

通過spirng.io建立的spring boot項目提供了一個空的測試檔案——bookpubapplicationtest.java,内容是:

在pom檔案中增加spring-boot-starter-test依賴,添加jsonpath依賴

在bookpubapplicationtest中添加測試用例

spring boot項目的代碼覆寫率

Spring Boot應用的測試——Mockito

cobertura統計代碼覆寫率

Spring Boot應用的測試——Mockito

單擊某個類進去,可以看到詳細資訊

首先分析在bookpubapplicationtests類中用到的注解:

@runwith(springjunit4classrunner.class),這是junit的注解,通過這個注解讓springjunit4classrunner這個類提供spring測試上下文。

@springapplicationconfiguration(classes = bookpubapplication.class),這是spring boot注解,為了進行內建測試,需要通過這個注解加載和配置spring應用上下文。這是一個元注解(meta-annoation),它包含了@contextconfiguration( loader = springapplicationcontextloader.class)這個注解,測試架構通過這個注解使用spring boot架構的springapplicationcontextloader加載器建立應用上下文。

@webintegrationtest("server.port:0"),這個注解表示目前的測試是內建測試(integration test),是以需要初始化完整的上下文并啟動應用程式。這個注解一般和@springapplicationconfiguration一起出現。server.port:0指的是讓spring boot在随機端口上啟動tomcat服務,随後在測試中程式通過@value("${local.server.port}")獲得這個端口号,并指派給port變量。當在jenkins或其他持續內建伺服器上運作測試程式時,這種随機擷取端口的能力可以提供測試程式的并行性。

了解完測試類的注解,再看看測試類的内部。由于這是spring boot的測試,是以我們可通過@autowired注解織入任何由spring管理的對象,或者是通過@value設定指定的環境變量的值。在現在這個測試類中,我們定義了webapplicationcontext和bookrepository對象。

每個測試用例用@test注解修飾。在第一個測試用例——contextloads()方法中,我僅僅需要确認bookrepository連接配接已經建立,并且資料庫中已經包含了對應的測試資料。

第二個測試用例用來測試我們提供的restful url——通過isbn查詢一本書,即“/books/{isbn}”。在這個測試用例中我們使用testresttemplate對象發起restful請求。

第三個測試用例中展示了如何通過mockmvc對象實作跟第二個測試類似的功能。spring測試架構提供mockmvc對象,可以在不需要用戶端-服務端請求的情況下進行mvc測試,完全在服務端這邊就可以執行controller的請求,跟啟動了測試伺服器一樣。

測試開始之前需要建立測試環境,setup方法被@before修飾。通過mockmvcbuilders工具,使用webapplicationcontext對象作為參數,建立一個mockmvc對象。

mockmvc對象提供一組工具函數用來執行assert判斷,都是針對web請求的判斷。這組工具的使用方式是函數的鍊式調用,允許程式員将多個測試用例連結在一起,并進行多個判斷。在這個例子中我們用到下面的一些工具函數:

perform(get(...))建立web請求。在我們的第三個用例中,通過mockmvcrequestbuilder執行get請求。

andexpect(...)可以在perform(...)函數調用後多次調用,表示對多個條件的判斷,這個函數的參數類型是resultmatcher接口,在mockmvcresultmatchers這這個類中提供了很多傳回resultmatcher接口的工具函數。這個函數使得可以檢測同一個web請求的多個方面,包括http響應狀态碼(response status),響應的内容類型(content type),會話中存放的值,檢驗重定向、model或者header的内容等等。這裡需要通過第三方庫json-path檢測json格式的響應資料:檢查json資料包含正确的元素類型和對應的值,例如jsonpath("$.name").value("中文測試")用于檢查在根目錄下有一個名為name的節點,并且該節點對應的值是“中文測試”。

問題描述:通過spring-boot-starter-data-rest建立的repository,取出的漢字是亂碼。

分析:使用postman和httpie驗證都沒問題,說明是mockmvc的測試用例寫得不對,應該主動設定用戶端如何解析http響應,用get.accept方法設定用戶端可識别的内容類型,修改後的測試用例如下:

<a href="http://ningandjiao.iteye.com/blog/1982635" target="_blank">基于spring-ws的restful api的內建測試</a>

<a href="http://www.bysocket.com/?p=282" target="_blank">j2ee要懂的小事—圖解http協定</a>

<a href="http://www.jayway.com/2014/07/04/integration-testing-a-spring-boot-application/" target="_blank">integration testing a spring boot application</a>

<a href="http://codetrips.com/2014/12/24/spring-boot-template-project/" target="_blank">spring boot project template</a>

<a href="http://www.jianshu.com/p/468a8fa752a7">— 在springboot應用的測試一文中,我們在starterrunner類的run(...)方法中給資料庫中添加一些初始資料。盡管通過程式設計方式添加初始資料比較快捷友善,但長期來看這并不是一個好辦法——特别是當需要添加的資料量很大時。我們開發最好把資料庫準備、資料庫修改和資料庫的配置與将要運作的程式代碼分離,盡管這僅僅是為測試用例做準備。springboot已經提供了相應的支援來完成這個任務。我們在之前的應用程式基礎上進行實驗。springboot提供兩種方法來定義資料庫的表結構以及添加資料。第一種方法是使</a>

<a href="http://www.jianshu.com/p/c1c495f231ea">— mockito.jpg前兩篇文章的主要内容是:為了給執行測試,如何建立資料庫表和導入初始資料。這裡我們将學習如何利用mockito架構和一些注解模拟(mock)repository執行個體,進而使得測試用例不依賴外部的資料庫服務。我們需要建立一個springboot配置類,在該類中定義用于測試的springbean;我們通過注解訓示springboot何時加載測試配置類以及何時執行該類中的代碼。在改配置類中,我們将使用mockito架構建立一些帶預定義方法的mock對象,springboot在執行測試用例之前</a>

<a href="http://www.jianshu.com/p/f1e354d382cd">— spock架構是基于groovy語言的測試架構,groovy與java具備良好的互操作性,是以可以在springboot項目中使用該架構寫優雅、高效以及dsl化的測試用例。spock通過@runwith注解與junit架構協同使用,另外,spock也可以和mockito(springboot應用的測試——mockito)協同使用。在這個小節中我們會利用spock、mockito一起編寫一些測試用例(包括對controller的測試和對repository的測試),感受下spock的使用。howdo根據bu</a>