java 在 JUnit 测试中处理 System.exit(0)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6141252/
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
Dealing with System.exit(0) in JUnit tests
提问by Ben
I am implementing some tests for an existing Java Swing application, so that I can safely refactor and extend the code without breaking anything. I started with some unit tests in JUnit, since that seems the simplest way to get started, but now my priority is to create some end-to-end tests to exercise the application as a whole.
我正在为现有的 Java Swing 应用程序实施一些测试,以便我可以安全地重构和扩展代码而不会破坏任何东西。我从 JUnit 中的一些单元测试开始,因为这似乎是最简单的开始方式,但现在我的首要任务是创建一些端到端测试来将应用程序作为一个整体来运行。
I am starting the application afresh in each test by putting each test method in a separate test case, and using the fork="yes"
option in Ant's junit
task. However, some of the use cases I would like to implement as tests involve the user exiting the application, which results in one of the methods calling System.exit(0). This is regarded by JUnit as an error: junit.framework.AssertionFailedError: Forked Java VM exited abnormally
.
我通过将每个测试方法放在一个单独的测试用例中,并使用fork="yes"
Antjunit
任务中的选项,在每个测试中重新启动应用程序。但是,我希望作为测试实现的一些用例涉及用户退出应用程序,这会导致调用 System.exit(0) 的方法之一。这被 JUnit 视为错误:junit.framework.AssertionFailedError: Forked Java VM exited abnormally
.
Is there a way to tell JUnit that exiting with a return code of zero is actually OK?
有没有办法告诉 JUnit 以零返回码退出实际上是可以的?
采纳答案by TofuBeer
How I deal with that is to install a security manager that throws an exception when System.exit is called. Then there is code that catches the exception and doesn't fail the test.
我的处理方法是安装一个安全管理器,在调用 System.exit 时抛出异常。然后是捕获异常并且不会使测试失败的代码。
public class NoExitSecurityManager
extends java.rmi.RMISecurityManager
{
private final SecurityManager parent;
public NoExitSecurityManager(final SecurityManager manager)
{
parent = manager;
}
public void checkExit(int status)
{
throw new AttemptToExitException(status);
}
public void checkPermission(Permission perm)
{
}
}
And then in the code, something like:
然后在代码中,类似于:
catch(final Throwable ex)
{
final Throwable cause;
if(ex.getCause() == null)
{
cause = ex;
}
else
{
cause = ex.getCause();
}
if(cause instanceof AttemptToExitException)
{
status = ((AttemptToExitException)cause).getStatus();
}
else
{
throw cause;
}
}
assertEquals("System.exit must be called with the value of " + expectedStatus, expectedStatus, status);
回答by Stefan Birkner
The library System Ruleshas a JUnit rule called ExpectedSystemExit. With this rule you are able to test code, that calls System.exit(...):
库系统规则有一个名为 ExpectedSystemExit 的 JUnit 规则。使用此规则,您可以测试调用 System.exit(...) 的代码:
public class MyTest {
@Rule
public final ExpectedSystemExit exit = ExpectedSystemExit.none();
@Test
public void systemExitWithArbitraryStatusCode() {
exit.expectSystemExit();
/* the code under test, which calls System.exit(...)
* with an arbitrary status
*/
}
@Test
public void systemExitWithSelectedStatusCode0() {
exit.expectSystemExitWithStatus(0);
//the code under test, which calls System.exit(0)
}
}
System Rules needs at least JUnit 4.9.
系统规则至少需要 JUnit 4.9。
Full disclosure: I'm the author of System Rules.
完全披露:我是系统规则的作者。
回答by Jon Skeet
Could you abstract out the "system exiting" into a new dependency, so that in your tests you could just have a fake which records the fact that exit has been called (and the value), but use an implementation which calls System.exit
in the real application?
您能否将“系统退出”抽象为一个新的依赖项,以便在您的测试中,您可以只使用一个伪造来记录退出已被调用的事实(和值),但使用System.exit
在实际应用程序中调用的实现?
回答by Todd
If anybody needs this functionality for JUnit 5, I've written an extensionto do this. This is a simple annotation you can use to tell your test case to expect and exit status code or a specific exit status code.
如果有人需要 JUnit 5 的这个功能,我已经写了一个扩展来做到这一点。这是一个简单的注释,您可以用来告诉您的测试用例期望并退出状态代码或特定的退出状态代码。
For example, any exit code will do:
例如,任何退出代码都可以:
public class MyTestCases {
@Test
@ExpectSystemExit
public void thatSystemExitIsCalled() {
System.exit(1);
}
}
If we want to look for a specific code:
如果我们要查找特定代码:
public class MyTestCases {
@Test
@ExpectSystemExitWithStatus(1)
public void thatSystemExitIsCalled() {
System.exit(1);
}
}