在终止代码上使用JUnit。

7 浏览
0 Comments

在终止代码上使用JUnit。

我正在尝试测试一个给定的Java应用程序,为此我想使用JUnit。我面临的问题是:一旦我要测试的代码完成工作,它会调用System.exit(),这会关闭应用程序。尽管它也会关闭JVM(我猜测),但它也阻止了我的测试完成。有没有办法解决这个问题,而不修改原始代码?最初我尝试从新线程启动我正在测试的应用程序,尽管显然没有太大区别。

0
0 Comments

使用JUnit对代码进行测试时出现问题的原因是代码中包含了System.exit()方法,而JUnit测试默认是在同一进程中运行的,无法绕过System.exit()方法的调用。解决这个问题的方法是调用应用程序以单独的进程运行,然后从单元测试中观察返回的错误级别。至于这是否足够提供测试通过的反馈,取决于个人的判断。

可能是正确的,但我不确定。我认为你可以使用powermock来模拟静态和final方法。我没有尝试过,所以不确定。

这是不正确的,你可以像上面和其他类似问题中所述,使用SecurityManager来解决这个问题。

好吧,我承认我错了。我不知道可以拦截System.exit()的调用。

0
0 Comments

问题出现的原因是在使用JUnit测试代码时,当代码中调用了System.exit(status)方法时,会触发JVM的安全管理器(SecurityManager)的checkExit(status)方法,如果该方法抛出了SecurityException异常,就会阻止代码的终止。为了解决这个问题,我们需要在JUnit测试类中设置一个安全管理器,重写checkExit(status)方法,让它抛出SecurityException异常。

解决方法如下:

在JUnit测试类的setUp()方法中设置一个安全管理器:

    securityManager = System.getSecurityManager();
    System.setSecurityManager(new SecurityManager() {
        public void checkExit(int status) {
            super.checkExit(status); // This is IMPORTANT!
            throw new SecurityException("Overriding shutdown...");
        }
    });

tearDown()方法中将安全管理器恢复到之前保存的实例,否则JUnit无法正常关闭。

参考资料:

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/SecurityManager.html

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/SecurityManager.html#checkExit(int)

SecurityManager类包含许多以check开头的方法。这些方法在Java库中的各种方法执行某些潜在敏感操作之前被调用。调用此类检查方法的示例通常如下所示:

     SecurityManager security = System.getSecurityManager();
     if (security != null) {
         security.checkXXX(argument,  . . . );
     }

安全管理器可以通过抛出异常来阻止操作的完成。如果操作被允许,安全管理器方法简单地返回,但如果不允许操作,则抛出SecurityException异常。

非常感谢您的答案。我很快就会进行测试。

必须在测试前添加(expected = SecurityException.class),然后它就可以正常工作了。

是的,在这里使用(expected=SecurityException.class)而不是捕获异常是完全合理的。感谢您接受答案。

是否有示例代码可以看看如何实现?

0
0 Comments

使用JUnit对终止的代码进行测试时,可能会出现以下问题:无法阻止应用程序关闭。为了解决这个问题,可以使用System Rules库中的ExpectedSystemExit规则。以下是如何使用它的示例代码:

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.Assertion;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;
public class SystemExitTest {
    public final ExpectedSystemExit exit = ExpectedSystemExit.none();
    
    public void executeSomeCodeAFTERsystemExit() {
        System.out.println("This is executed before everything.");
        
        exit.expectSystemExit();
        exit.checkAssertionAfterwards(new Assertion() {
            public void checkAssertion() throws Exception {
                System.out.println("This is executed AFTER System.exit()"+
                " and, if exists, the .junit.After annotated method!");
            }
        });
        
        System.out.println("This is executed right before System.exit().");
        System.exit(0);
        System.out.println("This is NEVER executed.");
    }
}

如果你使用Maven,可以将以下代码添加到pom.xml文件中:


    junit
    junit
    4.11


    com.github.stefanbirkner
    system-rules
    1.3.0

上述代码中使用了ExpectedSystemExit规则来预期System.exit()方法的调用,并在其后执行一些代码。这样可以在JUnit中执行一些System.exit()之后的操作,而不影响应用程序的关闭。

然而,有用户反馈称上述代码并没有阻止应用程序的关闭。经过进一步的验证,发现原因是缺少JUnit的@Rule注解。添加该注解后,代码可以正常工作,并在System.exit()方法被调用后执行相关代码。

,使用ExpectedSystemExit规则可以在JUnit中测试终止的代码,并在System.exit()方法被调用后执行额外的操作。这是一种优雅的解决方案,不会改变系统行为。

0