使用Powermock工具mock系統類的native方法(如System.currentTimeMillis()方法)

背景

有如下AppUtils類的getAppName方法需要做單元測試:

public class AppUtils {

    private static String appName = "";

    public static String getAppName() {
        if ("".equals(appName)) {
            return "app_" + System.currentTimeMillis();
        }
        return appName;
    }

}

假設,現在測試代碼中我用來判斷用例是否通過的條件爲調用getAppName方法的返回值是否與某個確定的字符串相等。But,在getAppName方法的內部實現中可以看到返回值的一部分是由System.currentTimeMillis的值組成,而這個值認爲不是一個恆定值,在測試中,我期望調用System.currentTimeMillis()方法時返回一個恆定值排除掉這個干擾因素。而System.currentTimeMillis的源碼如下:

public static native long currentTimeMillis();

那麼我的做法就是mock這個方法的返回值。

p.s. :github的維基上是有這個介紹的,我這裏就用我的這個示例具體進行說明,有興趣可以點擊這裏查看維基的示例。

下面根據測試代碼進行說明:

實現

@RunWith(PowerMockRunner.class) //1.
@PrepareForTest({AppUtils.class}) //2.
public class AppUtilsTest {

    @Before
    public void setup() {
        PowerMockito.mockStatic(System.class);//3
    }

    @Test
    public void testGetAppName() {
        Long currentTimeMillis = System.currentTimeMillis();//4.
        PowerMockito.when(System.currentTimeMillis()).thenReturn(currentTimeMillis);//5.
        assertEquals("app_" + currentTimeMillis, AppUtils.getAppName());
    }
}

maven的依賴可以參考我的 Mockito配合powermock工具mock構造函數這篇上的說明。

注意看上面測試代碼後面註釋的1、2、3、4、5。按這個順序講一下步驟:

1. 類上使用註解@RunWith(PowrMockRunner.class)

2. 類上使用的註解@PrepareFotTest括號裏的值聲明要處理的類是AppUtils.class,注意這裏是調用系統類的類AppUtils,而不是系統類System,雖然我們要mock的是System.currentTimeMillis()方法返回值。

3. 調用mockStatic方法mock System這個類

4. 這一步不主要,但是後面需要解釋下。我這裏是保存一個返回值變量。其實在這裏調用System.currentTimeMillis()方法的返回已經是默認值0了,也就是說變量currentTimeMillis的值是0,也算是個恆定值了達到我們預期了,當然這裏可以直接定義一個常量。

5. 設置調用System.currentTimeMillis()方法時的期望返回值。

其實重要的是上面的1、2、3、5步。按這幾步操作類似System.currentTimeMillis()這些方法便都可以mock它們的返回值了。

下面解釋下第2步和第4步。

第2步,我們在@PrepareFotTest註解裏聲明要處理的類是AppUtils,這是因爲Powermock在mock像System.currentTimeMillis()這種系統類的方法時實際修改的是調用這個方法的類的字節碼,而不是System類的。

第4步中,我們調用System.currentTimeMillis()方法返回值是0,是因爲在@Before註解的方法裏我mockStatic了System類,調用方法時返回了默認值。關於@Before註解的使用介紹可以看JUnit4的github上的維基,地址在這裏:https://github.com/junit-team/junit4/wiki/Test-fixtures

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章