10

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?

2
  • Did you add any new Configurations? SpringBootTest is looking for a configuration from a test package up to a project root. Commented May 16, 2017 at 13:43
  • No, I didn't introduce any new configurations and I didn't change the existing configurations. Commented May 17, 2017 at 15:40

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you. Unfortunately I can't use DbUnit. It is more important what is wrong with my existing test configuration.
Yes I understand that. But one more question - sql file is called "clean-data-in-all-tables.sql" - is it only used to delete (rollback) all data inserted into database during tests? Maybe you can end up with some solution where you don't need it? Something like using @Transactional on your test classes?
We used to use @DirtiesContext for cleaning the DB however it increases time consumed by test run in 2-3 times.
One more question - do you have some custom made task in gradle for running tests? Do you "play" with properties like maxParallelForks and forkFor and then your tests run in parallel and that's the reason why some falling when you run all of them, and not falling when you run one by one?
No, gradle task is not changed in any way

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.