测试场景
测试中有遇到一个测试超时的场景。 在系统中配置了一个timeout,默认譬如300S,程序在未达到timeout之前将持续进行。
如果要测试这个逻辑,就需要等候300S直到退出。对于单元测试来说,这个时间是不可接受的。因此,需要去修改这个private static final 。
测试代码
//常量类
public class Consts {
public static final long TIMEOUT= Long.parseLong("300000");
//public static final long TIMEOUT= 300000L;
public static final int LOGIN_SUCCESS=0;
}
////SUT
public class ConstsDemo {
public void longCall() throws Exception {
long begin = System.currentTimeMillis();
while(true) {
if(System.currentTimeMillis()-begin > Consts.TIMEOUT) {
System.out.println("timeout");
throw new Exception("timeout");
}
try {
Thread.sleep(100);
System.out.println(Consts.TIMEOUT);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
// 测试用例
@RunWith( PowerMockRunner.class )
@PrepareForTest({Consts.class} )
public class ConstsDemoTest {
@Test(expected=Exception.class,timeout=100000)
public void testConsts_TIMEOUT() throws Exception {
spy(Consts.class);
Whitebox.setInternalState(Consts.class, "TIMEOUT", -1L);
ConstsDemo demo= new ConstsDemo();
demo.longCall();
}
这里要注意的问题是, 对于value 为基本类型的无法进行Mock。
public static final long TIMEOUT= Long.parseLong("300000");
//public static final long TIMEOUT= 300000L;
如果使用 这样的定义,则whitebox将设置成功,但是runtime时无效,因为在JVM 中的不同内存区域。
即使使用了以下链接提供的反射方法也不行。
https://stackoverflow.com/questions/5385161/powermock-testing-set-static-field-of-class
static void setFinalStatic(Class clazz, String fieldName, Object newValue) throws NoSuchFieldException, IllegalAccessException {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
Field modifiers = field.getClass().getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
通过 javap -verbose Consts.class 查看,
//in-line ,请注意$jacocoInit,表示这段代码可以被jacoco打桩,而基础类型无法注入。 powermock也一样。
image image解决办法
放弃对于public static final long TIMEOUT= 300000L; 的mock,而转用去Mock以下这个方法,System.currentTimeMillis()
如以下代码:
spy(System.class);
when(System.currentTimeMillis()).thenCallRealMethod().thenReturn(Long.MAX_VALUE);
网友评论