【问题标题】:JUnit ClassRule executes code before Spring Boot application shut downJUnit ClassRule 在 Spring Boot 应用程序关闭之前执行代码
【发布时间】:2019-12-27 22:26:33
【问题描述】:

我正在使用 org.springframework.boot.test.context.SpringBootTest 运行 Spring Boot 集成测试。

我编写了一个 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 Boot 上下文关闭之前执行。

在 Spring 应用程序关闭后,我必须将代码放在哪里才能执行它?

【问题讨论】:

标签: java spring spring-boot junit junit4


【解决方案1】:

似乎所有ClassRules 的代码都首先执行,而Spring 上下文在JVM 终止之前被拆除(另见https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ConfigurableApplicationContext.html#registerShutdownHook--)。

【讨论】:

    【解决方案2】:

    对于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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-07
      • 2020-08-31
      • 2022-01-14
      相关资源
      最近更新 更多