引述:程序測試對保障應用程序正確 性而言,其重要性怎麼樣強調都不爲過。JUnit是必須事先掌握的測試框架,大多數測試框架和測試工具都在此基礎上擴展而來,Spring對測試所提供的 幫助類也是在JUnit的基礎上進行演化的。直接使用JUnit測試基於Spring的應用存在諸多不便,不可避免地須要將大量的精力用於應付測試夾具準 備、測試現場恢復、訪問測試數據操做結果等邊緣性的工做中。Mockito、Unitils、Dbunit等框架的出現,這些問題有了很好的解決方案,特 別是Unitils結合Dbunit對測試DAO層提供了強大的支持,大大提升了編寫測試用例的效率和質量。
也許在單元測試框架領域,testNG、JUnit的高下上尚有爭論,它們各有本身的擁躉,可是在測試模擬領域,Mockito無疑是翹楚,JMock等只能站後了。
模擬測試概述
目前支持Java語言的Mock測試工具備EasyMock、JMock、Mockito、MockCreator、Mockrunner、 MockMaker等,Mockito是一個針對Java的Mocking框架。它與EasyMock和JMock很類似,是一套經過簡單的方法對於指定 的接口或類生成 Mock 對象的類庫,避免了手工編寫Mock對象。但Mockito是經過在執行後校驗什麼已經被調用,它消除了對指望行爲(Expectations)的須要。 使用Mockito,在準備階段只需花費不多的時間,可使用簡潔的API編寫出漂亮的測試,能夠對具體的類建立Mock對象,而且有「監視」非Mock 對象的能力。
Mockito使用起來簡單,學習成本很低,並且具備很是簡潔的API,測試代碼的可讀性很高,所以它十分受歡迎,用戶羣愈來愈多,不少開源軟件也選擇了 Mockito。要想了解更多有關Mockito的信息,能夠訪問其官方網站http://www.mockito.org/。在開始使用Mockito 以前,先簡單瞭解一下Stub和Mock的區別。相比Easymock,JMock,編寫出來的代碼更加容易閱讀。無須錄製mock方法調用就返回默認值 是一個很大優點。目前最新的版本是1.9.0。
Stub對象用來提供測試時所須要的測試數據,能夠對各類交互設置相應的迴應。例如咱們能夠設置方法調用的返回值等。Mockito中 when(…).thenReturn(…) 這樣的語法即是設置方法調用的返回值。另外也能夠設置方法在什麼時候調用會拋出異常等。
Mock對象用來驗證測試中所依賴對象間的交互是否可以達到預期。Mockito中用 verify(…).methodXxx(…) 語法來驗證 methodXxx方法是否按照預期進行了調用。有關 stub和mock的詳細論述請見Martin Fowler的文章《Mocks Aren't Stub》,地址爲http://martinfowler.com/articles/mocksArentStubs.html。在Mocking框 架中所謂的Mock對象其實是做爲上述的Stub和Mock對象同時使用的。由於它既能夠設置方法調用返回值,又能夠驗證方法的調用。
建立Mock對象
能夠對類和接口進行Mock對象的建立,建立的時候能夠爲Mock對象命名,也能夠忽略命名參數。爲Mock對象命名的好處就是調試的時候會很方便。比 如,咱們Mock多個對象,在測試失敗的信息中會把有問題的Mock對象打印出來,有了名字咱們能夠很容易定位和辨認出是哪一個Mock對象出現的問題。另 外它也有限制,對於final類、匿名類和Java的基本類型是沒法進行Mock的。除了用Mock方法來建立模擬對象,如 mock(Class<T> classToMock),也可使用@mock註解定義Mock,下面咱們經過實例來介紹一下如何建立一個Mock對象。
html
在①處和②處,經過Mockito提供的mock()方法建立UserService 用戶服務接口、用戶服務實現類UserServiceImpl的模擬對象。在③處,經過@Mock註解建立用戶User類模擬對象,並須要在測試類初始化 方法中,經過MockitoAnnotations.initMocks()方法初始化當前測試類中全部打上@Mock註解的模擬對象。若是沒有執行這一 步初始化動做,測試時會報模擬對象爲空對象異常。
設定Mock對象的指望行爲及返回值
從上文中咱們已經知道能夠經過when(mock.someMethod()).thenReturn(value)來設定Mock對象的某個方法調用時 的返回值,但它也一樣有限制條件:對於static和final修飾的方法是沒法進行設定的。下面咱們經過實例來介紹一下如何調用方法及設定返回值。 框架
在①處,模擬測試接口UserService的findUserByUserName()方法、hasMatchUser()方法及 registerUser()方法。在①-1處經過when().thenReturn()語法,模擬方法調用及設置方法的返回值,實例經過模擬調用 UserService 用戶服務接口的查找用戶findUserByUserName()方法,查詢用戶名爲「tom」詳細的信息,並設置返回User對象:new User("tom", "1234")。在①-2處經過doReturn (). when ()語法,模擬判斷用戶hasMatchUser()方法的調用,判斷用戶名爲「tom」及密碼爲「1234」的用戶存在,並設置返回值爲:true。在 ①-3處對void方法進行方法預期設定,如實例中調用註冊用戶registerUser()方法。設定調用方法及返回值以後,就能夠執行接口方法調用驗 證。在②處和③處,模擬測試用戶服務實現類UserServiceImpl,測試的方法與模擬接口一致。
驗證交互行爲
Mock對象一旦創建便會自動記錄本身的交互行爲,因此咱們能夠有選擇地對其交互行爲進行驗證。在Mockito中驗證mock對象交互行爲的方法是 verify(mock). xxx()。因而用此方法驗證了findUserByUserName()方法的調用,由於只調用了一次,因此在verify中咱們指定了times參數 或atLeastOnce()參數。最後驗證返回值是否和預期同樣。 dom
Mockio爲咱們提供了豐富調用方法次數的驗證機制,如被調用了特定次數verify(xxx, times(x))、至少x次verify(xxx, atLeast (x))、最多x次verify(xxx, atMost (x))、從未被調用verify(xxx, never())。在①-6處,驗證findUserByUserName()方法至少被調用一次。在①-7處,驗證 findUserByUserName()方法至多被調用一次。ide
http://stamen.iteye.com/blog/1470066工具