今天的component有个commandline class需要测试main函数的返回值,我们知道正常情况下是无法测试commandline的类的,因为 public static final void main(String[] args) {}结束的时
候会调用system.exit(status).当然也会终止测试的jvm。也就是说如果我们直接这样写: public void testStatus(){ CommandLineClass.main(args); } 这是行不通的,一是你无法获得返回值,而是后边的语句和测试全部会被强行终止。当然任何难题都有解决的办法,我们知道main函数返回的系统调用exit,会经过securityManage的检查是否拥有权限。所以我们可以实现自己的securitymanager并覆写 checkExit(int status) 方法,保存status状态,这样就搞定了。简单吧? 这个是我刚才写的SecurityManager:
/** * the mock security manager use for retrieve the exit status of the main method. * <p> * since the main method will call System.exit, we cannot make it executable with other tests because JVM * will be halt once main() method is called. so we can "stop" and "ignore" the exit call execute. * </p> * @author netsafe */ class MockSecurityManager extends SecurityManager { /** * the status value of the exit method. */ private int status; /** * Throws a <code>SecurityException</code> if the calling thread is not allowed to cause the Java * Virtual Machine to halt with the specified status code. * <p>for this mock method,the SecurityException will always be thrown</p> * @param status * the exit status. * @exception SecurityException * if the calling thread does not have permission to halt the Java Virtual Machine with * the specified status. */ @Override public void checkExit(int status) { this.status = status; throw new SecurityException(); } /** * return the exit status. * @return the exit status. */ public int getStatus() { return status; } /** * mock method for ignore the permission check. * @param perm * the requested permission. */ @Override public void checkPermission(Permission perm) { // does nothing } /** * mock method for ignore the permission check. * @param perm * the specified permission * @param context * a system-dependent security context. */ @Override public void checkPermission(Permission perm, Object context) { // does nothing } } 这个是测试用的方法:
/** * execute the CommandLineClass.main method and check the exit status. * @param args * the arguments for the main method * @param expectedStatus * the expected exit status */ private void assertExecuteStatus(String[] args, int expectedStatus) { // backup the security manager. SecurityManager oldManager = System.getSecurityManager(); MockSecurityManager manager = new MockSecurityManager(); System.setSecurityManager(manager); try { CommandLineClass.main(args); } catch (SecurityException e) { // ignore } assertEquals("the return status should be " + expectedStatus, expectedStatus, manager.getStatus()); // restore the security manager System.setSecurityManager(oldManager); }