2009年4月4日 星期六

[JUnit] 如何測試一個 private method

上次幫老師帶了一堂課後,那天同學有反應說關於測試的問題:要如何測試 private method 呢?這個問題好像有點難,不過如果我們利用 Java 提供的 reflection 機制就可以輕鬆的辦到!不過那也要會用才行囉!所以我就示範一下如何撰寫這樣的程式。
假設我們有一個程式如下:
public class HavePrivateMethod
{
private int add(int x, int y)
{
return x + y;
}
}

這個程式很簡單,可能你連用都不想用XD,不過因為是示範就別太計較了!反正就是有個 private method 為 add,parameter 與 return type 都是 int。以下就是我們的測試程式:

public class HavePrivateMethodTest
{
@Test
public void add() throws Exception
{
int x = 1;
int y = 2;
int expectedResult = 3;
/*
* 1.取得 instance
*/
HavePrivateMethod havePrivateMethodClass =
HavePrivateMethod.class.newInstance();
/*
* 2.取得我們要測試的 method
*/
Method addMethod =
havePrivateMethodClass.getClass().getDeclaredMethod(
"add",int.class,int.class);
/*
* 3.設定存取性
*/
addMethod.setAccessible(true);
/*
* 4.實際呼叫
*/
Object actualResult =
addMethod.invoke(havePrivateMethodClass, x, y);
addMethod.setAccessible(false);
Assert.assertEquals(expectedResult, actualResult);
}
}

總之,我們要先取得一個該 class 的 instance,再來就是設定我們要測試的 private method,要取得此 method 的 Method instance,由於我們測試的 private method 有兩個 primitive type 的 int,所以我們就用 int.class,而不是用 Integer.class 喔!因為這不一樣的~
取得 Method instance 後,我們就要先設定讓此 method 是可以被存取的,接下來才是呼叫(invoke) 此 method,呼叫後的回傳值一律都是 Object 型態,我們就透過 JUnit 提供的 assertEquals() method 來幫助我們檢查!
這樣就完成我們的目標囉~

NOTE:(2009-05-06)
在上面的範例程式中,我們採用 HavePrivateMethod.class.newInstance(); 來初始化被測試的物件,不過這樣的初始化動作只限定用在被測的 class 具備有 default constructor!如果我們的被測試 class 沒有 default constructor 的話,我們就只能用一般的初始化方式,也就是 new Object 囉~這樣在 method reflection 也是會有效的!
感謝學弟大頭跟 Fred 提出這樣的問題~

沒有留言: