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

2023-05-16

背景

有如下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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Powermock工具mock系统类的native方法(如System.currentTimeMillis()方法) 的相关文章

随机推荐