我正在使用junit与docker运行一些集成测试 .
我有一个自定义TestRule来在某个测试失败时从容器中复制日志:
public static class CopyLogsOnTestFailure implements TestRule {
@Override
public Statement apply(Statement base, Description description) {
return statement(base, description);
}
private Statement statement(final Statement base, Description description) {
return new Statement() {
final String pathToFolder = "/tmp/logs";
@Override
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (Throwable caughtThrowable) {
logger.error("Copyings logs on failure!");
copyLogs(pathToFolder);
throw caughtThrowable;
}
}
};
}
现在,如果测试在@BeforeClass中失败,则不会复制日志,因为TestRule对@BeforeClass或@AfterClass方法没有好处 .
我尝试使用类似的@ClassRule来测试它,但是当@FeforeClass中的testfails运行时,它运行@AfterClass,然后运行规则 . 显然,在我的情况下,@ AfterClass删除容器 .
知道如何解决这个问题吗?
1 回答
一般命令JUnit将执行代码如下(blog post with sample code):
我已经对执行进行了处理,因此如果在什么级别上引发异常,您可以更容易地看到将执行哪些清理代码 .
在第一个使用简单JUnit
@Rule
注释规则的情况下,异常发生在执行规则之前,这解释了@AfterClass
代码的执行 .在第二种情况下,首先执行
@ClassRule
代码,然后执行@BeforeClass
中的代码,产生异常 . Junit现在将尝试执行已执行方法的清理代码 . 首先执行@AfterClass
,然后执行@ClassRule
清理 .您可以将
@BeforeClass
和@AfterClass
重构为另一个规则和chain them together with the other rule,但您可能会注意到相同的行为,因为外部规则在内部规则之前执行,如果内部失败,则执行内部规则的清理,然后清除外在规则 . 如果外部规则失败,则根本不执行内部规则 .基本上你想要的,如果我理解你的意图正确,是为
@AfterClass
清理创建一个外部规则,它正在进行清理工作,如下所示:@BeforeClass
的代码可以放入其他规则中然后创建一个像这样的链规则:
JUnit将首先调用外部规则(
CleanUpRule
)并调用base.evaluate()
方法,该方法将调用下一个规则CopyLogsOnTestFailure
,该规则也只是将调用传播到下一个规则InitializationRule
. 如果此规则失败,则由于缺少异常处理程序,异常将传播到先前规则CopyLosOnTestFailure
,异常处理程序将在该规则中启动并将日志复制到其他位置 . 当异常被重新抛出时,异常现在由第一个规则CleanUpRule
处理,该规则只执行finally块,因此执行前@AfterClass
清理 .