在Spring启动之前如何在JUnit中运行代码?

时间:2019-04-18 09:01:41

标签: spring-test

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

  

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

到目前为止已尝试并失败:

扩展SpringJUnit4ClassRunner得到一个类,该类的构造函数可以在初始化Spring之前运行自定义代码。失败,因为super(testClass)必须被称为第一件事,并且已经做了很多阻碍工作的事情。

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

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

2 个答案:

答案 0 :(得分:1)

一种方法是忽略SpringRunner,而使用the equivalent combinationSpringClassRule中的SpringMethodRule。然后,您可以包裹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 verison测试)

我认为您没有比这更“容易”的了。至于其他选项,您还可以签出@BootstrapWith@TestExecutionListeners批注。

答案 1 :(得分:0)

补充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-test 4.3.9.RELEASE,我不得不覆盖spring-corespring-tx,再加上javax.servlet的{​​{1}},并使用更高版本使这项工作。