'How to execute code in a SpringBootTest before the Application is run?

I have a SpringBoot based command line application. The application creates or deletes some records in a database. It does so not directly via JDBC but rather through a special API (instance variable dbService).

The application class looks like this:

@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
  }

}

Now I'd like to create a SpringBoot test that would run the whole application with a configuration specially prepared for the test.

I run the test with an in-memory DB (H2) which is empty at the test start. Hence I'd like to insert some records into the DB -- as the setup for the test. The code for inserting the records must be executed

  1. After the Spring context has been loaded -- so that I can use the bean dbService.

  2. Before the Application is run -- so that the application runs with the prepared DB.

Somehow I fail to implement the above two points.

What I have so far is this:

@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
  }
 
}

My problem is that the the method preparedDbForTheTest does not seem to get executed at all.

According to the SpringBoot docs, the event ApplicationReadyEvent is sent exactly when I want to execute the setup code. But somehow the code is not executed.

If I annotate the method with @Before... (I tried several variants of it) then it gets executed, but after the Application class has run.

What am I doing wrong?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source