EasyMock基本使用
我們的第一個例子非常簡單,但是在現實情況下,你通常是在一些類里使用另外的一些類。在進行真正的測試之前,你可能需要做很多的工作,比喻說安置大量的環境代碼,啟動一種大型的、復雜的系統,可能是數據庫、工作流或者是某一種類型的IDE環境,你的預設環境代碼需要是系統進入某種特定的狀態,以便按照測試所需要的方法進行響應。但是這種工作不大可能很快就能完成。
??為了對一部分類進行單元測試,你需要建立和控制另外一些類。最好的辦法就是為需要測試的類創建一個模擬對象。你可以自己手工的編寫類,也可以使用EasyMock來產生這些對象。模擬對象提供了一種經過證明是成功的解決方案。
??當我們很難或不可能為某種難以處理的資源創建需要的狀態或者存取某種資源受限時,你就可以使用模擬對象。
??模擬對象取代真實對象的位置,用于測試一些與真實對象進行交互或依賴于真實對象的功能。模擬對象背后的基本思想就是創建輕量級的、可控制的對象來代替為了編寫測試為需要使用的對象。模擬對象還能夠讓你指定和測試你的代碼與模擬對象本身之間的交互。
說的再直白一點,一個模擬對象就是一個簡單的接口或者是類,在里面你可以定義一個特定的方法調用之后的簡單的輸出。
?
使用Junit和Easy Mock
從EasyMock到主頁上下載EasyMock, 把下載得到的easymock.jar增加到你的classpath中。
創建一個Java工程JavaMockTest,創建下面的這些類。
IncomeCalculator是要被測試的類,這個類用來根據一個人的職位來計算一個人的工資的方法。?
?
package?income;public?enum?Position {BOSS, PROGRAMMER, SURFER}?
package?income.exceptions;
public?class?PositionException?extends?RuntimeException {
private?static?final?long?serialVersionUID = 1L;
public?PositionException(String message) {
super(message);
}?
package?income.exceptions;
public?class?CalcMethodException?extends?RuntimeException {
private?static?final?long?serialVersionUID = 1L;
public?CalcMethodException(String message) {
super(message);
}?
package?income.method;
import?income.Position;
public?interface?ICalcMethod {
public?abstract?double?calc(Position position);
}
package?income;
import?income.exceptions.CalcMethodException;
import?income.exceptions.PositionException;
import?income.method.ICalcMethod;
public?class?IncomeCalculator{
private?ICalcMethod calcMethod;
private?Position position;
public?void?setCalcMethod(ICalcMethod calcMethod){
this.calcMethod = calcMethod;
}
public?void?setPosition(Position position){
this.position = position;
public?double?calc (){
if?(calcMethod==null){
throw?new?CalcMethodException("CalcMethod not yet maintained");
}
if?(position==null){
throw?new?PositionException("Position not yet maintained");
}
return?calcMethod.calc(position);
}
?
使用Eclipse的JUnit功能為IncomeCalulator創建一個測試。在我的例子中,我同時創建一個新的源文件夾,名字為"test",我把我創建的測試類全部放到里面。
?下面就是一個使用EasyMock創建的測試。?
?
package?income;import?static?org.junit.Assert.assertEquals;
import?static?org.junit.Assert.fail;
import?income.exceptions.CalcMethodException;
import?income.exceptions.PositionException;
import?income.method.ICalcMethod;
import?org.easymock.EasyMock;
import?org.junit.Before;
import?org.junit.Test;?
public?class?IncomeCalculatorTest {?
private?ICalcMethod calcMethod;
private?IncomeCalculator calc;?
@Before
public?void?setUp()?throws?Exception {
calcMethod = EasyMock.createMock(ICalcMethod.class);
calc =?new?IncomeCalculator();
}
@Test
public?void?testCalc1() {
// Setting up the expected value of the method call calc
EasyMock.expect(calcMethod.calc(Position.BOSS)).andReturn(70000.0).times(2);
EasyMock.expect(calcMethod.calc(Position.PROGRAMMER)).andReturn(50000.0);
// Setup is finished need to activate the mock
EasyMock.replay(calcMethod);?
calc.setCalcMethod(calcMethod);
try?{
calc.calc();
fail("Exception did not occur");
}?catch?(PositionException e) {
}
calc.setPosition(Position.BOSS);
assertEquals(70000.0, calc.calc());
assertEquals(70000.0, calc.calc());
calc.setPosition(Position.PROGRAMMER);
assertEquals(50000.0, calc.calc());
calc.setPosition(Position.SURFER);
EasyMock.verify(calcMethod);
}
@Test(expected = CalcMethodException.class)
public?void?testNoCalc() {
calc.setPosition(Position.SURFER);
calc.calc();
}
@Test(expected = PositionException.class)
public?void?testNoPosition() {
EasyMock.expect(calcMethod.calc(Position.BOSS)).andReturn(70000.0);
EasyMock.replay(calcMethod);
calc.setCalcMethod(calcMethod);
calc.calc();
}
@Test(expected = PositionException.class)
public?void?testCalc2() {
// Setting up the expected value of the method call calc
EasyMock.expect(calcMethod.calc(Position.SURFER)).andThrow(new?PositionException("Don't know?this?guy")).times(1);?
// Setup is finished need to activate the mock
EasyMock.replay(calcMethod);
calc.setPosition(Position.SURFER);
calc.setCalcMethod(calcMethod);
calc.calc();
}
?
?
?
?
?
?
?
??expect方法告知EasyMock希望得到一個特定的方法,使用一些特定的參數,addReturn為某一個方法定義返回值。times方法定義了模擬對象將被調用幾次。?reply方法需要在讓模擬對象可用之前被調用。執行完測試之后,你可以調用verify方法來檢查模擬對象是不是跟預期的一樣被調用了。
?
1、mock次數的設置
times(int count): 要以范圍的方式定義調用次數,能夠使用其他方法代替times(int count): times(int min, int max) to?expect between?min?and?max?calls, 用上下限指定方法調用次數。 atLeastOnce() to?expect at least one call, and 指定該方法至少被調用一次。 anyTimes() to?expected an unrestricted number of calls. 不限制對該方法的調用。
?
2、接口、抽象類、類的mock
org.easymock.classextension.EasyMock 被用來mock抽象類(abstract)和具體類?
org.easymock.EasyMock被用來mock接口(interface)?
3、創建多個 Mock 對象,EasyMock 提供了另外一種生成和管理 Mock 對象的機制
| IMocksControl control = EasyMock.createControl(); java.sql.Connection mockConnection = control.createMock(Connection.class); java.sql.Statement mockStatement = control.createMock(Statement.class); java.sql.ResultSet mockResultSet = control.createMock(ResultSet.class); |
?4、多個接口進行mock, 且之間存在相互關系, 例子如下:
?
?
?本文轉自 tianya23 51CTO博客,原文鏈接:http://blog.51cto.com/tianya23/268397,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的EasyMock基本使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 格式化磁盘
- 下一篇: rocketmq消费负载均衡--push