easymock教程-strict和nice
在easymock的使用過程中,當(dāng)創(chuàng)建mock對象時,我們會遇到 strict mock和nice mock的概念。
比如創(chuàng)建mock對象我們通常使用EasyMock.createMock(),但是我們會發(fā)現(xiàn)easymock同時提供了兩個類似的方法:


類似的在創(chuàng)建MocksControl時,除了通常的EasyMock.createControl() 外,easymock也同時提供兩個類似的方法:


我們來看看strict和nice有什么作用。參考easymock的javadoc,我們對比createMock()和createStrictMock():
EasyMock.createMock(): Creates a mock object that implements the given interface, order checking is disabled by default.
EasyMock.createNiceMock() : Creates a mock object that implements the given interface, order checking is enabled by default.
發(fā)現(xiàn)strict mock方式下默認(rèn)是開啟調(diào)用順序檢測的,而普通的mock方式則默認(rèn)不開啟調(diào)用順序檢測。
再看一下createNiceMock():
Creates a mock object that implements the given interface, order checking is disabled by default, and the mock object will return 0, null or false for unexpected invocations.
和createMock()相同的是默認(rèn)不開啟調(diào)用順序檢測,另外有一個非常有用的功能就是對于意料之外的調(diào)用將返回0,null 或者false.之所以說有用,是因為在我們的實際開發(fā)過程中,有時候會有這樣的需求:對于某個mock對象的調(diào)用(可以是部分,也可以是全部),我們完全不介意調(diào)用細(xì)節(jié),包括是否調(diào)用和調(diào)用順序,參數(shù),返回值,我們只要求mock對象容許程序可以繼續(xù)而不是拋出異常報告說 unexpected invocations 。nice mock在這種情況下可以為我們節(jié)省大量的工作量,非常方便。
我們來看一個簡單的實際使用的例子,假設(shè)我們有一個Business類,依賴于兩個service 接口:
先看只調(diào)用一個依賴的情況,注意在record階段service1.method2()和service1.method1()的順序和business.executeService1()方法中的實際調(diào)用順序是故意設(shè)置為不同的。








































1. 普通mock

















測試案例可以通過,說明EasyMock.createMock()的確是不檢測方法的調(diào)用順序。
2. strict mock








案例失敗,錯誤信息如下
java.lang.AssertionError:
Unexpected method call service1.method1():
service1.method2(): expected: 1, actual: 0
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:45)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:73)
at net.sourcesky.study.easymock.tutorial.$Proxy4.method1(Unknown Source)
at net.sourcesky.study.easymock.tutorial.OrderTest$Business.executeService1(OrderTest.java:14)
at net.sourcesky.study.easymock.tutorial.OrderTest.testStrictMock(OrderTest.java:79)
......
說明strict mock下,easymock檢測到了實際調(diào)用時的順序和預(yù)期的不同。
3. nick mock






測試案例可以通過,而且如果是nick mock的話,record階段可以簡化:










這個簡化版本的測試案例也是可以通過的。
上述的測試案例驗證了strict mock和nice mock的基本使用,對于同一個mock對象,strict模式下多個方法之間的調(diào)用順序在record階段和replay階段下是需要保持一致的。但是故事并不是到此結(jié)束,更有意思的內(nèi)容在后面:如果出現(xiàn)多個mock對象,那么這些不同mock對象的方法之間,他們的調(diào)用順序是否檢測?普通mock和nice mock模式下自然是不會檢測順序,但是strict模式下呢?
我們來看需要測試的方法executeService1And2(),這個方法會依次調(diào)用service1和service2的方法。使用easymock測試這個方法,注意我們在record階段依然故意將方法的調(diào)用順序設(shè)置為和實際不同。
1. 不使用control,直接創(chuàng)建兩個strict mock對象

















這個測試案例,出于意外的,通過了。easymock并沒有檢測service1.method1()和service2.method3()這兩個方法的調(diào)用順序。
2. 使用strict control創(chuàng)建兩個strict mock對象






案例失敗,錯誤信息為:
java.lang.AssertionError:
Unexpected method call service1.method1():
service2.method3(): expected: 1, actual: 0
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:45)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:73)
at net.sourcesky.study.easymock.tutorial.$Proxy4.method1(Unknown Source)
at net.sourcesky.study.easymock.tutorial.OrderTest$Business.executeService1And2(OrderTest.java:19)
at net.sourcesky.study.easymock.tutorial.OrderTest.testWithStrictControlInWrongOrder(OrderTest.java:218)
......
OK,easymock終于檢測到service1.method1()和service2.method3()這兩個方法的調(diào)用順序和期望的不一致了。
解釋一下,EasyMock.createStrictMock()方法實際上內(nèi)部是生成一個新的strict control,然后再創(chuàng)建mock對象。
Service1 service1 = EasyMock.createStrictMock("service1", Service1.class);
Service2 service2 = EasyMock.createStrictMock("service2", Service2.class);
這里實際是創(chuàng)建了兩個strict control,而easymock是不會跨control進(jìn)行順序檢測的。在實際使用過程中,我們會有大量的場景需要檢測多個mock之間的調(diào)用順序(按說如果沒有特殊要求,一般的測試場景默認(rèn)都應(yīng)該如此),這種情況下就必須使用control, 而且必須是同一個strict control才能滿足要求。
教程后面的最佳實踐中有一條就是推薦使用mock control,可以跨mock對象檢測方法調(diào)用順序是一個重要原因。
posted on 2010-11-19 11:39 sky ao 閱讀(2627) 評論(0) 編輯 收藏 所屬分類: software test