PowerMocker,Mockito和Junit 備忘
1. JUnit 是基礎,進行單元測試.
參考:http://www.ibm.com/developerworks/cn/java/j-lo-junit4/
1.1 JUnit的常用Annoation:
1. @Test: 測試方法,可以有兩個參數(expected=XXException.class,timeout=xxx)
expected 表示期待一個異常,如果實際拋出異常就是這個期待的異常則表示通過測試,
timeout設置一個超時時間,如果測試超過這個時間,則表示測試不通過
2. @Ignore: 忽略測試方法
3. @Before: 每一個測試方法之前運行
4. @After: 每一個測試方法之後運行
5. @BeforeClass: 所有測試開始之前運行,該方法必須是 Public 和 Static 的.
6. @AfterClass: 所有測試結束之後運行,並且該方法必須是 Public 和 Static 的
1.2參數化測試。
你可能遇到過這樣的函數,它的參數有許多特殊值,或者說他的參數分爲很多個區域。
比如,一個對考試分數進行評價的函數,返回值分別爲"優秀,良好,一般,及格,不及格",
因此你在編寫測試的時候,至少要寫 5 個測試,把這 5 中情況都包含了,這確實是一件很麻煩的事情。
我們還使用我們先前的例子,測試一下"計算一個數的平方"這個函數,暫且分三類:正數, 0,負數。
測試代碼如下:
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert. * ;
public class AdvancedTest
{
private static Calculator calculator = new Calculator();
@Before
public void clearCalculator()
{
calculator.clear();
}
@Test
public void square1()
{
calculator.square( 2 );
assertEquals( 4, calculator.getResult());
}
@Test
public void square2()
{
calculator.square( 0 );
assertEquals( 0, calculator.getResult());
}
@Test
public void square3()
{
calculator.square( - 3 );
assertEquals( 9, calculator.getResult());
}
}
爲了簡化類似的測試, JUnit4 提出了"參數化測試"的概念,只寫一個測試函數,
把這若干種情況作爲參數傳遞進去,一次性的完成測試。代碼如下:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.util.Arrays;
import java.util.Collection;
@RunWith(Parameterized.class )
public class SquareTest
{
private static Calculator calculator = new Calculator();
private int param;
private int result;
@Parameters
public static Collection data()
{
return Arrays.asList( new Object[][] {{ 2,4 },{ 0,0},{-3,9 },});
}
// 構造函數,對變量進行初始化
public SquareTest( int param, int result)
{
this .param = param;
this .result = result;
}
@Test
public void square()
{
calculator.square(param);
assertEquals(result, calculator.getResult());
}
}
下面我們對上述代碼進行分析。首先,你要爲這種測試專門生成一個新的類,而不能與其他測試共用同一個類,
此例中我們定義了一個SquareTest類。然後,你要爲這個類指定一個Runner,而不能使用默認的Runner了,
因爲特殊的功能要用特殊的Runner嘛。
@RunWith(Parameterized.class)這條語句就是爲這個類指定了一個ParameterizedRunner。
第二步,定義一個待測試的類,並且定義兩個變量,一個用於存放參數,
一個用於存放期待的結果。接下來,定義測試數據的集合,也就是上述的data()方法,
該方法可以任意命名,但是必須使用@Parameters標註進行修飾。
這個方法的框架就不予解釋了,大家只需要注意其中的數據,是一個二維數組,數據兩兩一組,
每組中的這兩個數據,一個是參數,一個是你預期的結果。
比如我們的第一組{2, 4},2就是參數,4就是預期的結果。
這兩個數據的順序無所謂,誰前誰後都可以。
之後是構造函數,其功能就是對先前定義的兩個參數進行初始化。
在這裏你可要注意一下參數的順序了,要和上面的數據集合的順序保持一致。
如果前面的順序是{參數,期待的結果},那麼你構造函數的順序
也要是"構造函數(參數, 期待的結果)",反之亦然。
最後就是寫一個簡單的測試例了,和前面介紹過的寫法完全一樣,在此就不多說。
1.3 打包測試。
通過前面的介紹我們可以感覺到,在一個項目中,只寫一個測試類是不可能的,我們會寫出很多很多個測試類。
可是這些測試類必須一個一個的執行,也是比較麻煩的事情。
鑑於此, JUnit 爲我們提供了打包測試的功能,將所有需要運行的測試類集中起來,
一次性的運行完畢,大大的方便了我們的測試工作。具體代碼如下:
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class )
@Suite.SuiteClasses( {CalculatorTest. class,SquareTest. class } )
public class AllCalculatorTests
{
}
大家可以看到,這個功能也需要使用一個特殊的 Runner,因此我們需要向 @RunWith 標註傳遞一個參數 Suite.class 。
同時,我們還需要另外一個標註 @Suite.SuiteClasses,來表明這個類是一個打包測試類。
我們把需要打包的類作爲參數傳遞給該標註就可以了。
有了這兩個標註之後,就已經完整的表達了所有的含義,因此下面的類已經無關緊要,
隨便起一個類名,內容全部爲空既可。
1.4 JUnit中的Assert方法
junit中的assert方法全部放在Assert類中,總結一下junit類中assert方法的分類。
(1) assertTrue/False([String message,]boolean condition);
判斷一個條件是true還是false。感覺這個最好用了,不用記下來那麼多的方法名。
(2) fail([String message,]);
失敗,可以有消息,也可以沒有消息。
(3) assertEquals([String message,]Object expected,Object actual);
判斷是否相等,可以指定輸出錯誤信息。
第一個參數是期望值,第二個參數是實際的值。
這個方法對各個變量有多種實現。在JDK1.5中基本一樣。
但是需要主意的是float和double最後面多一個delta的值,可能是誤差範圍,不確定這個 單詞什麼意思,汗一個。
(4) assertNotNull/Null([String message,]Object obj);
判讀一個對象是否非空(非空)。
(5) assertSame/NotSame([String message,]Object expected,Object actual);
判斷兩個對象是否指向同一個對象。看內存地址。
(6) failNotSame/failNotEquals(String message, Object expected, Object actual)
當不指向同一個內存地址或者不相等的時候,輸出錯誤信息。
注意信息是必須的,而且這個輸出是格式化過的。
2. Mockito
參考:http://rritw.com/a/bianchengyuyan/C__/20120919/226505.html
Mockito 是基於JUnit的,用於單元測試的一個模擬(mock)框架.所謂模擬(mock)是指在單元測試中,
假如我們要測試的類A中需要依賴B類的一個實例,而B類的這個實例在單元測試代碼中
不容易獲取到.例如,需要測試的類是專門用來測試發送郵件的,假如
就叫MailSender吧,這個類中需要依賴一個User類的實例的email address,通常這個User實例只有在用戶
登錄系統時才能獲取到,而要測試的這個MailSender時(只是單元測試而已),
爲了獲取到User實例,而在單元測試代碼中進行一系列登錄授權神馬的操作顯然太繁瑣了,於是mock就派上用場了.
可以使用 User user = mock(User.class); 這樣就獲得了一個模擬的User實例了.
獲取到模擬的User實例還只是開始,因爲發郵件時,
需要調用User.getMailAddress()方法獲取用戶的email,
假如調用了剛剛生成的模擬的User實例的getMailAddress()方法會返回什麼呢?
這是mockito框架又發威了,因爲它可以模擬方法調用的返回值,也就是說可以設置方法的預期返回值:
使用代碼:
when(user.getMailAddress()).thenReturn( "[email protected]" );
使用when(...).thenReturn(...) 格式表示,假如後續代碼中有調用
user.getMailAddress()則返回"[email protected]",真是太和諧了.
(注意: 創建mock對象不能對final,Anonymous ,primitive類進行mock)
另外,可對方法設定返回異常
mockito詳細文檔:
http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html
3. PowerMocker
PowerMock 也是一個單元測試模擬框架,它是在其它單元測試模擬框架的基礎上做出的擴展。
通過提供定製的類加載器以及一些字節碼篡改技巧的應用,PowerMock 現了對靜態方法、
構造方法、私有方法以及 Final 方法的模擬支持,對靜態初始化過程的移除等強大的功能。
因爲 PowerMock 在擴展功能時完全採用和被擴展的框架相同的 API, 熟悉 PowerMock 所
支持的模擬框架的開發者會發現 PowerMock 非常容易上手。PowerMock 的目的就是在當前
已經被大家所熟悉的接口上通過添加極少的方法和註釋來實現額外的功能,
目前,PowerMock 僅支持 EasyMock 和 Mockito。
參考:http://www.ibm.com/developerworks/cn/java/j-lo-powermock/