Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@SpringBootTest with @Sql: order of script execution and context initialization

I have integration tests that are executed on top on inmemory database. The signature of each test looks more or less like this:

@RunWith(SpringRunner.class)
@SpringBootTest
@Sql("/clean-data-in-all-tables.sql")
public class SomeTest { 
    @Test
    public void shouldDoSomehting() {}
}

During test-context initialization the DB schema is recreated by Hibernate:

spring:
  jpa:
    hibernate:
      ddl-auto: create-drop

I expect sql script to be executed after initialization of context and after db schema generation. However in some cases clean-data-in-all-tables.sql is executed before schema generation and it fails because it expects tables which were not yet created.

I have more than 500 tests written in the way I explained and they all were working well until I added few more similar tests.

Tests fail when I execute them together via Gradle or IntelliJ. Note the failed tests are not the tests which were recently added. This are the old tests totally unrelated to the ones I added. What is also strange is that the failed tests work well if I run them one by one through IntelliJ.

It looks like a bug of spring-boot however I still try to find a way to workaround it. At the same time I tried numerous of things to solve the issue however none of them was helpfull.

Please share your ideas on what could help and what could be wrong with my code.

UPDATE: Found the workaround: changing the spring.jpa.hibernate.ddl-auto from create-drop to create solves the problem.

But the question is still open what is the reason of such strange behaviour?

like image 871
Sasha Shpota Avatar asked May 11 '17 11:05

Sasha Shpota


People also ask

How does @SpringBootTest work?

@SpringBootTest This annotation works by creating the ApplicationContext used in our tests through SpringApplication. It starts the embedded server, creates a web environment and then enables @Test methods to do integration testing. By default, @SpringBootTest does not start a server.

Which annotation is used for testing Spring MVC which apply only the configuration related to MVC test?

Again, very similar to the @DataJpaTest and the @DataMongoTest annotations, to perform classic Spring MVC tests, we apply the @WebMvcTest annotation alongside the @RunWith(SpringRunner. class) annotation. Keep in mind that the effects of this annotation only apply to the MVC infrastructure.

What annotation causes JUnit to let spring boot control the test?

Spring Boot provides a @SpringBootTest annotation, which can be used as an alternative to the standard spring-test @ContextConfiguration annotation when you need Spring Boot features. The annotation works by creating the ApplicationContext used in your tests through SpringApplication .


1 Answers

One possible solution (I'm not sure if you are open for using DBUnit) can be:

1) Create Abstract Repository Integration Test:

@TestExecutionListeners({DbUnitTestExecutionListener.class})
@SpringApplicationConfiguration(classes = Application.class)
@DirtiesContext
public abstract class AbstractRepositoryIT extends AbstractTransactionalJUnit4SpringContextTests {
}

2) Create "real" integration test:

@DatabaseSetup(SomeEntityRepositoryIT.DATASET)
@DatabaseTearDown(type = DatabaseOperation.DELETE_ALL, value = {"dataset.xml})
public class SomeEntityRepositoryIT extends AbstractRepositoryIT {
...
}

In file dataset.xml you can set up initial state for your tests etc... More can be found here

like image 134
nick79 Avatar answered Oct 13 '22 23:10

nick79