java 在终止的代码上使用 JUnit
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15990433/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using JUnit on code that terminates
提问by Giannis
I am trying to test a given java application, and for that purpose I want to use JUnit.
我正在尝试测试给定的 Java 应用程序,为此我想使用 JUnit。
The problem I am facing is the following: Once the code I am trying to test finishes its work, its calling System.exit()
, which closes the application. Although it is also stoping my tests from completing, as it closes the JVM (I assume).
我面临的问题如下:一旦我尝试测试的代码完成其工作,它的调用System.exit()
就会关闭应用程序。虽然它也阻止了我的测试完成,因为它关闭了 JVM(我假设)。
Is there anyway to go around this problem, without modifying the original code? Initially I tried launching the application im testing from new thread, although that obviously didn't make much difference.
有没有办法解决这个问题,而不修改原始代码?最初我尝试从新线程启动即时测试应用程序,尽管这显然没有太大区别。
回答by acdcjunior
You can use System Rules: "A collection of JUnit rules for testing code which uses java.lang.System
."
您可以使用系统规则:“用于测试使用 的代码的 JUnit 规则集合java.lang.System
。”
Among their rules, you have ExpectedSystemExit
, below is an example on how to use it. I believe it is a very clean solution.
在他们的规则中,你有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 {
@Rule
public final ExpectedSystemExit exit = ExpectedSystemExit.none();
@Test
public void noSystemExit() {
//passes
}
@Test
public void executeSomeCodeAFTERsystemExit() {
System.out.println("This is executed before everything.");
exit.expectSystemExit();
exit.checkAssertionAfterwards(new Assertion() {
@Override
public void checkAssertion() throws Exception {
System.out.println("This is executed AFTER System.exit()"+
" and, if exists, the @org.junit.After annotated method!");
}
});
System.out.println("This is executed right before System.exit().");
System.exit(0);
System.out.println("This is NEVER executed.");
}
@Test
public void systemExitWithArbitraryStatusCode() {
exit.expectSystemExit();
System.exit(0);
}
@Test
public void systemExitWithSelectedStatusCode0() {
exit.expectSystemExitWithStatus(0);
System.exit(0);
}
@Test
public void failSystemExit() {
exit.expectSystemExit();
//System.exit(0);
}
}
If you use maven, you can add this to your pom.xml
:
如果您使用 maven,您可以将其添加到您的pom.xml
:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.3.0</version>
</dependency>
回答by Ravi Thapliyal
System.exit(status)
actually delegates the call to Runtimeclass. Runtimebefore proceeding with this shutdown request invokes checkExit(status)
on JVM's current SecurityManagerwhich can prevent the impending shutdown by throwing a SecurityException.
System.exit(status)
实际上将调用委托给运行时类。继续执行此关闭请求之前的运行时会在checkExit(status)
JVM 的当前SecurityManager上调用,它可以通过抛出SecurityException来防止即将关闭。
Usually, the SecurityManagerneeds to establish if the current thread has the privilege to shutdown defined by the current security policy in place but since all we need is to recover from this exit call we simply throw a SecurityExceptionthat we'll now have to catch in our JUnit test case.
通常,SecurityManager需要确定当前线程是否具有由当前安全策略定义的关闭权限,但由于我们只需要从这个退出调用中恢复,我们只需抛出一个我们现在必须捕获的SecurityException我们的 JUnit 测试用例。
In your JUnit test class, setup a SecurityManagerin setUP()
method:
在您的 JUnit 测试类中,在方法中设置一个SecurityManagersetUP()
:
securityManager = System.getSecurityManager();
System.setSecurityManager(new SecurityManager() {
@Override
public void checkExit(int status) {
super.checkExit(status); // This is IMPORTANT!
throw new SecurityException("Overriding shutdown...");
}
});
In tearDown()
replace the SecurityManageragain with the instance that we saved before. Failure to do so would prevent JUnit from shutting down now! :)
在tearDown()
更换安全管理器与我们以前保存的情况下再次。如果不这样做,将阻止 JUnit 现在关闭!:)
References:
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)
参考资料:
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)
The SecurityManager class contains many methods with names that begin with the word check. These methods are called by various methods in the Java libraries before those methods perform certain potentially sensitive operations. The invocation of such a check method typically looks like this:
SecurityManager 类包含许多名称以单词 check 开头的方法。在 Java 库中的各种方法执行某些可能敏感的操作之前,这些方法会调用这些方法。此类检查方法的调用通常如下所示:
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkXXX(argument, . . . );
}
The security manager is thereby given an opportunity to prevent completion of the operation by throwing an exception. A security manager routine simply returns if the operation is permitted, but throws a SecurityException if the operation is not permitted.
因此,安全管理器有机会通过抛出异常来阻止操作的完成。如果操作被允许,安全管理器例程简单地返回,但如果操作不被允许,则抛出 SecurityException。
回答by bluevoid
There is no way around System.exit() except for calling the application to run as a seperate proces (outside your JVM).
除了调用应用程序作为单独的进程(在 JVM 之外)运行之外,没有其他方法可以绕过 System.exit()。
You can do this from your unit test and observe the errorlevel that comes back from it. Whether that gives enough feedback on passing of the test is up to your judgement.
您可以从单元测试中执行此操作并观察从中返回的错误级别。这是否对通过测试提供了足够的反馈取决于您的判断。