My Spring-Boot-Mvc-Web application has the following database configuration in application.properties
file:
spring.datasource.url=jdbc:h2:tcp://
If you use spring.jpa.hibernate.ddl-auto=create-drop
should be enough to create/drop database?
Unless you're using some kind of Spring-Data integration (which I don't know at all), this seems like custom logic you'll need to implement yourself. Spring doesn't know about your databases, its schemas, and tables.
Assuming JUnit, write appropriate @Before
and @After
methods to set up and clean up your database, its tables, and data. Your tests can themselves write the data they need, and potentially clean up after themselves if appropriate.
You can annotate your test class with @Transactional
:
import org.springframework.transaction.annotation.Transactional;
...
...
@RunWith(SpringRunner.class)
@Transactional
public class MyClassTest {
@Autowired
private SomeRepository repository;
@Before
public void init() {
// add some test data, that data would be rolled back, and recreated for each separate test
repository.save(...);
}
@Test
public void testSomething() {
// add some more data
repository.save(...);
// update some base data
repository.delete(...);
// all the changes on database done in that test would be rolled back after test finish
}
}
All tests are wrapped inside a transaction, that is rolled back at the end of each test. There are unfortunately some problems with that annotation of course, and you need to pay special attention, when for example your production code uses transactions with different score.
Using the accepted answer in Spring-Boot 2.2.0, I was seeing JDBC syntax errors related to constraints:
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Constraint "FKEFFD698EA2E75FXEERWBO8IUT" already exists; SQL statement: alter table foo add constraint FKeffd698ea2e75fxeerwbo8iut foreign key (bar) references bar [90045-200]
To fix this, I added @AutoConfigureTestDatabase
to my unit test (part of spring-boot-test-autoconfigure):
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.boot.test.context.SpringBootTest;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
@AutoConfigureTestDatabase(replace = Replace.ANY)
public class FooRepositoryTest { ... }
With spring boot the h2 database can be defined uniquely for each test. Just override the data source URL for each test
@SpringBootTest(properties = {"spring.config.name=myapp-test-h2","myapp.trx.datasource.url=jdbc:h2:mem:trxServiceStatus"})
The tests can run in parallel.
Within the test the data can be reset by
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
To create the database you have to do what the other answers say with the spring.jpa.hibernate.ddl-auto=create-drop
, now if your intent is to pupulate the database on each test then spring provides a very usefull anotation
@Transactional(value=JpaConfiguration.TRANSACTION_MANAGER_NAME)
@Sql(executionPhase=ExecutionPhase.BEFORE_TEST_METHOD,scripts="classpath:/test-sql/group2.sql")
public class GroupServiceTest extends TimeoffApplicationTests {
that is from this package org.springframework.test.context.jdbc.Sql;
and you can run a before test method and a after test method. To populate the database.
Regarding creating the database each time, Say you only want your Test to have the create-drop option you can configure your tests with a custom properties with this annotation
@TestPropertySource(locations="classpath:application-test.properties")
public class TimeoffApplicationTests extends AbstractTransactionalJUnit4SpringContextTests{
Hope it helps