【问题标题】:How can I run code in JUnit before Spring starts?如何在 Spring 开始之前在 JUnit 中运行代码?
【发布时间】:2019-04-18 09:01:41
【问题描述】:

如何在 Spring 开始之前在我的 @RunWith(SpringRunner.class) @SpringBootTest(classes = {...}) JUnit 测试中运行代码?

这个问题已经被问过好几次了(例如12),但总是被一些配置建议或其他“解决”,从来没有一个通用的答案。请不要质疑我将要在该代码中做什么,而只是建议一种干净的方法。

到目前为止尝试并失败:

扩展SpringJUnit4ClassRunner 以获得一个类,其构造函数可以在初始化 Spring 之前运行自定义代码。失败是因为必须首先调用super(testClass),并且已经做了很多妨碍工作的事情。

扩展Runner 以获得一个委托给SpringRunner 的类,而不是继承它。此类可以在实际实例化 SpringRunner 之前在其构造函数中运行自定义代码。但是,此设置失败,并出现诸如 java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig 之类的模糊错误消息。 “模糊”是因为我的测试没有网络配置,因此不应该干预会话和 cookie。

添加在 Spring 加载其上下文之前触发的 ApplicationContextInitializer。这些东西很容易添加到实际的 @SpringApplication 中,但很难添加到 Junit 中。他们在这个过程中也很晚,很多春天已经开始了。

【问题讨论】:

  • 我测试了“Extend Runner”选项,它对我有用。您可能应该提供有关您的场景的更多详细信息:spring 版本、最小化和匿名化的测试用例。对于“扩展 SpringJUnit4ClassRunner”选项,您的构造函数可能如下所示:public MyCustomSpringRunner(Class<?> clazz) throws InitializationError { super(doSomethingAndPassthrough(clazz)); };` 您在静态方法 doSomethingAndPassthrough 中执行您的操作,然后返回作为参数传入的类。

标签: spring-test


【解决方案1】:

一种方法是省略SpringRunner 并使用SpringClassRuleSpringMethodRule 中的the equivalent combination 代替。然后你可以包装 SpringClassRule 并在它启动之前做你的事情:

public class SomeSpringTest {

    @ClassRule
    public static final TestRule TestRule = new TestRule() {
            private final SpringClassRule springClassRule =
                new SpringClassRule();

            @Override
            public Statement apply(Statement statement, Description description) {
                System.out.println("Before everything Spring does");
                return springClassRule.apply(statement, description);
            }
        };

    @Rule
    public final SpringMethodRule springMethodRule = new SpringMethodRule();

    @Test
    public void test() {
        // ...
    }
}

(使用 5.1.4.RELEASE Spring 版本测试)

我不认为你能得到比这更多的“之前”。至于其他选项,您还可以查看 @BootstrapWith@TestExecutionListeners 注释。

【讨论】:

    【解决方案2】:

    补充 jannis 对问题的评论,创建替代 JUnit 运行器并让它委托给 SpringRunner 的选项确实工作:

    public class AlternativeSpringRunner extends Runner {
    
        private SpringRunner springRunner;
    
        public AlternativeSpringRunner(Class testClass) {
            doSomethingBeforeSpringStarts();
            springRunner = new SpringRunner(testClass);
        }
    
        private doSomethingBeforeSpringStarts() {
            // whatever
        }
    
        public Description getDescription() {
            return springRunner.getDescription();
        }
    
        public void run(RunNotifier notifier) {
            springRunner.run(notifier);
        }
    
    }
    

    基于spring-test4.3.9.RELEASE,我必须覆盖spring-corespring-tx,加上javax.servletservlet-api 使用更高版本才能完成这项工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-03
      • 1970-01-01
      • 1970-01-01
      • 2012-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多