如果被测方法中存在系统退出语句,测试过程会直接终止,测试方法无法获取System.exit(statusCode);
语句中的状态码。
如果需要在测试方法中对系统退出状态码进行判断,可以通过覆盖Java默认的SecurityManager来实现。
因为System.exit(statusCode)
实际会将退出操作委托给Runtime类,Runtime类在执行Shutdown前会先调用当前VM的SecurityManager的checkExit(statusCode)
方法,如果checkExit抛出异常,则系统退出终止。
因此我们可以重写SecurityManager的checkExit方法,通过抛出异常的方式将statusCode
传递出来。
示例程序
下面程序演示如何在测试方法中执行main
方法,并获取其退出状态码。
- 被测程序
public class HelloWorld {
public static void main(String[] args) {
System.exit(1);
}
}
- 自定义SecurityManager类
注意:需要重写checkPermission
方法为空方法。
import java.security.Permission;
public class ExitCheckSecurityManager extends SecurityManager {
/**
* 临时托管系统原有SecurityManager
*/
private SecurityManager delegateSecurityManager;
public ExitCheckSecurityManager(SecurityManager delegateSecurityManager) {
this.delegateSecurityManager = delegateSecurityManager;
}
@Override
public void checkExit(int status) {
super.checkExit(status);
System.setSecurityManager(this.delegateSecurityManager);
throw new ExitSecurityException(status);
}
@Override
public void checkPermission(Permission permission) {
}
public static class ExitSecurityException extends SecurityException {
public final int status;
public ExitSecurityException(int status) {
this.status = status;
}
}
}
- 测试类
import static org.junit.Assert.*;
import org.junit.Test;
public class HelloWorldTest {
@Test
public void testMain() {
System.setSecurityManager(new ExitCheckSecurityManager(System.getSecurityManager()));
try {
HelloWorld.main(null);
fail();
} catch (ExitCheckSecurityManager.ExitSecurityException e) {
assertEquals(1, e.status);
}
}
}