JUnit ClassRule 在 Spring 引导应用程序关闭之前执行代码
JUnit ClassRule executes code before Spring Boot application shut down
我正在 运行 Spring 启动集成测试 org.springframework.boot.test.context.SpringBootTest
。
我已经编写了一个 JUnit 4 org.junit.rules.TestRule
,我正在使用它 org.junit.ClassRule
。
看起来像这样:
public class MyRule implements TestRule {
public Statement apply(final Statement statement, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
// do something
try {
statement.evaluate();
} finally {
// clean up
}
}
};
}
}
不幸的是,//清理代码在 Spring 引导上下文关闭之前执行。
Spring 应用程序关闭后,我必须将代码放在哪里才能执行它?
似乎所有 ClassRule
的代码都首先执行,并且 Spring 上下文在 JVM 终止之前被拆除(另请参阅 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ConfigurableApplicationContext.html#registerShutdownHook--)。
关于 spring 的测试,我建议使用 Spring 测试执行侦听器。
规则是 JUnit 的特定功能,并且由于 spring 作为 Runner (@RunWith(SpringRunner.class)
) 与 JUnit 集成,它们可能会产生干扰。
所以,回到那些测试执行监听器。基本上它是一个由 Spring 本身管理的侦听器,它提供了测试生命周期的挂钩,您可以在其中清理代码
这是一个例子:
public class MySampleListener implements TestExecutionListener {
@Override
public void beforeTestClass(TestContext testContext) throws Exception {
System.out.println("beforeTestClass");
}
@Override
public void prepareTestInstance(TestContext testContext) throws Exception {
System.out.println("prepareTestInstance");
}
@Override
public void beforeTestMethod(TestContext testContext) throws Exception {
System.out.println("beforeTestMethod");
}
@Override
public void afterTestMethod(TestContext testContext) throws Exception {
System.out.println("afterTestMethod");
}
@Override
public void afterTestClass(TestContext testContext) throws Exception {
System.out.println("afterTestClass");
}
}
如果您不需要所有方法,您可以使用 org.springframework.test.context.support.AbstractTestExecutionListener
,它为所有这些方法提供了一个空的实现。
现在,在测试中你提供了一个注解 @TestExecutionListeners
:
@RunWith(SpringRunner.class)
... // stuff like @ContextConfiguration
@TestExecutionListeners(value = {MySampleListener.class, ...})
public class MySampleTest {
@Test
public void testFoo() {
//test me
}
}
如果你想合并spring默认运行的其他监听器,你可以使用这个注解如下:
@TestExecutionListeners(value = MySampleListener.class,
mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
我正在 运行 Spring 启动集成测试 org.springframework.boot.test.context.SpringBootTest
。
我已经编写了一个 JUnit 4 org.junit.rules.TestRule
,我正在使用它 org.junit.ClassRule
。
看起来像这样:
public class MyRule implements TestRule {
public Statement apply(final Statement statement, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
// do something
try {
statement.evaluate();
} finally {
// clean up
}
}
};
}
}
不幸的是,//清理代码在 Spring 引导上下文关闭之前执行。
Spring 应用程序关闭后,我必须将代码放在哪里才能执行它?
似乎所有 ClassRule
的代码都首先执行,并且 Spring 上下文在 JVM 终止之前被拆除(另请参阅 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ConfigurableApplicationContext.html#registerShutdownHook--)。
关于 spring 的测试,我建议使用 Spring 测试执行侦听器。
规则是 JUnit 的特定功能,并且由于 spring 作为 Runner (@RunWith(SpringRunner.class)
) 与 JUnit 集成,它们可能会产生干扰。
所以,回到那些测试执行监听器。基本上它是一个由 Spring 本身管理的侦听器,它提供了测试生命周期的挂钩,您可以在其中清理代码 这是一个例子:
public class MySampleListener implements TestExecutionListener {
@Override
public void beforeTestClass(TestContext testContext) throws Exception {
System.out.println("beforeTestClass");
}
@Override
public void prepareTestInstance(TestContext testContext) throws Exception {
System.out.println("prepareTestInstance");
}
@Override
public void beforeTestMethod(TestContext testContext) throws Exception {
System.out.println("beforeTestMethod");
}
@Override
public void afterTestMethod(TestContext testContext) throws Exception {
System.out.println("afterTestMethod");
}
@Override
public void afterTestClass(TestContext testContext) throws Exception {
System.out.println("afterTestClass");
}
}
如果您不需要所有方法,您可以使用 org.springframework.test.context.support.AbstractTestExecutionListener
,它为所有这些方法提供了一个空的实现。
现在,在测试中你提供了一个注解 @TestExecutionListeners
:
@RunWith(SpringRunner.class)
... // stuff like @ContextConfiguration
@TestExecutionListeners(value = {MySampleListener.class, ...})
public class MySampleTest {
@Test
public void testFoo() {
//test me
}
}
如果你想合并spring默认运行的其他监听器,你可以使用这个注解如下:
@TestExecutionListeners(value = MySampleListener.class,
mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)