單元測試之--groovy的DSL測試

如何寫出更好的單元測試java

做爲一個大型電商後臺業務系統,系統的穩定性和可用性有很高的要求。良好以及高覆蓋的單元測試是其中重要的一環。在平常項目開發中時常會思考如何才能更加低成本,可讀性高以及維護性高的單元測試方式。spring

目前負責的系統,做爲一個銜接上下游的中間系統,有十分複雜的業務場景以及衆多的RPC調用,一般一個域的系統單元測試就超過500個,因此在單元測試上歷來沒有中止過探索和優化。框架

RPC Mock

首先爲了可以更好的完成RPC調用的mock,針對公司的RPC框架編寫了一個對應的mock服務。 一、擴展SpringJUnitClassRunner,在createTest中初始化一個本地的RPC服務,同時執行了全部的RPC服務目標地址爲本地 二、整合mockito實現對象的mock。mockito是java經常使用的mock框架,因此對於使用者來講機會是零成本。工具

BeanMock

Mock只是解決了RPC調用的問題,可是對於測試過程當中不少的嵌套調用mock的場景,每每都是經過很複雜的反射方式實現。反射方式在實現上麻煩不說,最嚴重的就是反射設置了mock對象以後,在測試完成以後並無將mock對象還原回真實的值。因爲整個測試都是使用同一個spring上下文(經過spring註解能夠實現每次都是新的上下文,可是影響測試執行效率),致使其餘單元測試失敗。而且這些單元測試失敗的緣由都是十分難排查的。單元測試

事實上一些其餘的mock組件可以實現private的mock,甚至是靜態對象的mock,好比power mock。 但基於整個團隊二三十人都是使用mockito的狀況下,轉爲使用另一個mock組件,無言之間引入了新的使用以及維護成本。因此爲了解決這個問題,基於spring的bean的特性,實現了Bean Mock,經過註解就能實現對嵌套對象的mock,十分簡潔。詳細介紹參見:BeanMock的使用介紹與說明測試

使用Groovy編寫類DSL的單元測試

上面的兩個Mock都是解決了單元測試過程當中的mock問題,除了對象的mock以外,單元測試更多的工做是在測試數據的構造,場景的模擬以及最終執行結果的斷言驗證。這個時候groovy的語言特性以及其對java的無縫結合就派上用場。 同時參加平常項目的QA用例評審過程當中,是對一個個業務場景的設計。這些測試用例能夠看做特定的領域語言來描述特定的業務場景。優化

好比對於電商平臺庫存扣減的場景來講,從訂單庫存領域,描述一個典型的業務場景以下:spa

一個訂單,購買兩個sku。其中一個是A庫存,須要3件;另一個是B庫存,須要2件。庫存都佔用成功。 執行訂單庫存扣減,驗證結果:訂單庫存佔用成功,佔用明細有3個。佔用明細1:佔用數2 ….net

經過Groovy的語言特性,能夠編寫基於上面這個特定的領域語言,經過DSL的方式來進行單元測試,代碼實例以下:設計

@Test 
 void testSingleOrderJit() throws OspException { 
 	makeRequest { 
 		header { 
 			detailList { 
 				[invType: Inv.A ] 
 			} 
 		} 
 	}withOccupy OccupancyResult.success execute{ 
 		oimsService.allocateOccupancy(it) 
 	} verify{ 
 		validateHeader { 
 			[status:3, detailNum:1] 
 		} 
 		validateDetail { 
 			[occupancyQty:-10, isShortAlloc:2] 
 			} 
 		} 
 	}
}

從上面的代碼看出,Groovy的語言特性在測試數據的構造以及斷言上,相比java語言更爲清晰與簡潔。

示例中試圖經過定義:

  1. makeRequest
  2. withInv
  3. withBrand
  4. withOccupancy

這樣的領域名詞幫助測試數據的模擬。好比在示例中就使用makeRequest建立了一個訂單,有一個明細,明細是Inv.A的庫存。經過withOccupancy來模擬這些庫存都是能佔用成功的。

經過定義execute,在execute中觸發所要測試的業務方法

經過定義:

  1. verify
  2. verifyHeader
  3. verifyDetail

領域名詞來幫助執行業務方法執行的結果驗證。

上述的例子是一個很簡單的DSL語言用法,但願經過逐漸完善領域的DSL,讓單元測試(其實這個階段在不少人看來屬於功能測試的範疇)具備可描述的特性。更加可以表達單元測試的意圖,從各類數據構造和測試驗證的場景中抽離出來,專一於要驗證的結果。

 

固然,這個並不能適用於全部的單元測試場景,應該結合實際的場景和測試目選擇合適的工具。這裏目的是爲了提供一種思路做爲參考

相關文章
相關標籤/搜索