如何在运行应用程序之前在SpringBootTest中执行代码



我有一个基于SpringBoot的命令行应用程序。应用程序在数据库中创建或删除一些记录。它不是直接通过JDBC实现的,而是通过一个特殊的API(实例变量dbService(实现的。

应用程序类如下所示:

@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
private DbService dbService;

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Override
public void run(String... args) {
// Do something via dbService based on the spring properties
}
}

现在我想创建一个SpringBoot测试,它将使用专门为测试准备的配置来运行整个应用程序。

我使用内存中的DB(H2(运行测试,该DB在测试开始时为空。因此,我想在数据库中插入一些记录——作为测试的设置。插入记录的代码必须执行

  1. 加载Spring上下文之后——这样我就可以使用beandbService了。

  2. 在应用程序运行之前——以便应用程序使用准备好的DB运行。

不知怎么的,我没能实现以上两点。

到目前为止,我所拥有的是:

@SpringBootTest
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
@ActiveProfiles("specialtest")
public class MyAppTest {

@Autowired
private DbService dbService;

private static final Logger logger = LoggerFactory.getLogger(MyAppTest.class);

// The expectation is that this method is executed after the spring context
// has been loaded and all beans created, but before the Application class
// is executed.
@EventListener(ApplicationStartedEvent.class)
public void preparedDbForTheTest() {
// Create some records via dbService
logger.info("Created records for the test");
}

// This test is executed after the application has run. Here we check
// whether the DB contains the expected records.
@Test
public void testApplication() {
// Check the DB contents
}

}

我的问题是方法preparedDbForTheTest似乎根本没有被执行。

根据SpringBoot文档,事件ApplicationReadyEvent正是在我想要执行安装代码的时候发送的。但不知何故,代码没有被执行。

如果我用@Before...注释该方法(我尝试了它的几种变体(,那么它就会被执行,但在之后,Application类就会运行。

我做错了什么?

测试类不是Spring管理的bean,因此@EventListener方法之类的东西将被忽略。

对于您的问题,最传统的解决方案是添加一些声明@EventListener:的@TestConfiguration

@SpringBootTest
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class MyAppTest {

private static final Logger logger = LoggerFactory.getLogger(MyAppTest.class);

@Test
public void testApplication() {
}

@TestConfiguration
static class DatabasePreparation {
@EventListener(ApplicationStartedEvent.class)
public void preparedDbForTheTest() {
logger.info("Created records for the test");
}
}

}

@TestConfiguration是可添加的,因此它将与应用程序的主配置一起使用。preparedDbForTheTest方法现在将被调用,作为刷新测试的应用程序上下文的一部分。

请注意,由于应用程序上下文缓存,不会对每个测试都调用此方法。它只会作为刷新上下文的一部分被调用,然后可以在几个测试之间共享。

最新更新