I am testing TestContainers and I would like to know how to populate a database executing a .sql file to create the structure and add some rows.
How to do it?
You can use DatabaseRider, which uses DBUnit behind the scenes, for populating test database and TestContainers as the test datasource. Following is a sample test, full source code is available on github here.
@RunWith(SpringRunner.class)
@SpringBootTest
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @ActiveProfiles("integration-test")
@DBRider //enables database rider in spring tests
@DBUnit(caseInsensitiveStrategy = Orthography.LOWERCASE) //https://stackoverflow.com/questions/43111996/why-postgresql-does-not-like-uppercase-table-names
public class SpringBootDBUnitIt {
private static final PostgreSQLContainer postgres = new PostgreSQLContainer(); //creates the database for all tests on this file
@PersistenceContext
private EntityManager entityManager;
@Autowired
private UserRepository userRepository;
@BeforeClass
public static void setupContainer() {
postgres.start();
}
@AfterClass
public static void shutdown() {
postgres.stop();
}
@Test
@DataSet("users.yml")
public void shouldListUsers() throws Exception {
assertThat(userRepository).isNotNull();
assertThat(userRepository.count()).isEqualTo(3);
assertThat(userRepository.findByEmail("springboot@gmail.com")).isEqualTo(new User(3));
}
@Test
@DataSet("users.yml") //users table will be cleaned before the test because default seeding strategy
@ExpectedDataSet("expected_users.yml")
public void shouldDeleteUser() throws Exception {
assertThat(userRepository).isNotNull();
assertThat(userRepository.count()).isEqualTo(3);
userRepository.delete(userRepository.findOne(2L));
entityManager.flush();//can't SpringBoot autoconfigure flushmode as commit/always
//assertThat(userRepository.count()).isEqualTo(2); //assertion is made by @ExpectedDataset
}
@Test
@DataSet(cleanBefore = true)//as we didn't declared a dataset DBUnit wont clear the table
@ExpectedDataSet("user.yml")
public void shouldInsertUser() throws Exception {
assertThat(userRepository).isNotNull();
assertThat(userRepository.count()).isEqualTo(0);
userRepository.save(new User("newUser@gmail.com", "new user"));
entityManager.flush();//can't SpringBoot autoconfigure flushmode as commit/always
//assertThat(userRepository.count()).isEqualTo(1); //assertion is made by @ExpectedDataset
}
}
src/test/resources/application-integration-test.properties
spring.datasource.url=jdbc:tc:postgresql://localhost/test
spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.datasource.username=test
spring.datasource.password=test
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
#spring.jpa.properties.org.hibernate.flushMode=ALWAYS #doesn't take effect
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
And finally the datasets:
src/test/resources/datasets/users.yml
users:
- ID: 1
EMAIL: "dbunit@gmail.com"
NAME: "dbunit"
- ID: 2
EMAIL: "rmpestano@gmail.com"
NAME: "rmpestano"
- ID: 3
EMAIL: "springboot@gmail.com"
NAME: "springboot"
src/test/resources/datasets/expected_users.yml
users:
- ID: 1
EMAIL: "dbunit@gmail.com"
NAME: "dbunit"
- ID: 3
EMAIL: "springboot@gmail.com"
NAME: "springboot"
src/test/resources/datasets/user.yml
users:
- ID: "regex:\\d+"
EMAIL: "newUser@gmail.com"
NAME: "new user"