如何在Spring启动之前在@RunWith(SpringRunner.class)
@SpringBootTest(classes = {...})
JUnit测试中运行代码?
这个问题已经问过好几次了(例如1,2),但总是被某些配置建议或其他“解决”,从来没有一个普遍的答案。请不要怀疑我在该代码中要做什么,而只是建议一种干净的方法。
到目前为止已尝试并失败:
扩展SpringJUnit4ClassRunner
得到一个类,该类的构造函数可以在初始化Spring之前运行自定义代码。失败,因为super(testClass)
必须被称为第一件事,并且已经做了很多阻碍工作的事情。
扩展Runner
以获得一个委托给SpringRunner
的类,而不是继承它。在实际实例化SpringRunner之前,此类可以在其构造函数中运行自定义代码。但是,此安装失败,并出现诸如 java.lang.NoClassDefFoundError:javax / servlet / SessionCookieConfig 之类的模糊错误消息。 “晦涩”是因为我的测试没有网络配置,因此不应该混入会话和Cookie。
添加一个ApplicationContextInitializer
,它在Spring加载上下文之前触发。这些东西很容易添加到实际的@SpringApplication中,但是很难添加到Junit中。他们的过程也很晚,许多Spring已经开始。
答案 0 :(得分:1)
一种方法是忽略SpringRunner
,而使用the equivalent combination和SpringClassRule
中的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-core
和spring-tx
,再加上javax.servlet
的{{1}},并使用更高版本使这项工作。