Giriş
Not : TestContainer yerine zonky kullanılabilir.
Test @TestContainers anotasyonu mecburen eklenir
Maven
Örnek
Şu satırı dahil ederiz
<properties><testcontainers.version>1.16.0</testcontainers.version></properties><dependency><groupId>org.testcontainers</groupId><artifactId>junit-jupiter</artifactId><scope>test</scope></dependency><dependency><groupId>org.testcontainers</groupId><artifactId>postgresql</artifactId><scope>test</scope></dependency><dependencyManagement><dependencies><dependency><groupId>org.testcontainers</groupId><artifactId>testcontainers-bom</artifactId><version>${testcontainers.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
Örnek
Eğer dependencyManagement kullanmak istemiyorsak şöyle yaparız
<dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers</artifactId> <version>1.16.3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>junit-jupiter</artifactId> <version>1.16.3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>postgresql</artifactId> <version>1.16.3</version> <scope>test</scope> </dependency>
TestContainer ile PostgreSQL kullanmak için iki yöntem var.
1. Test veri tabanı bilgisi src/test/resources/application.yml altında saklanır
2. Teste @Container anotasyonu eklenir
3. TestContainer Sınıfından Kalıtma
1. Yml Kullanımı
Örnek
Şöyle yaparız
limizde şöyle bir application.yml olsun. Burada jdbc connection string "tc" ile başlıyor.
spring.datasource.url=jdbc:tc:postgresql://localhost/testdb spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver spring.datasource.username=user spring.datasource.password=password spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto=update
Örnek
Elimizde şöyle bir application.yml olsun. Burada jdbc connection string "tc" ile başlıyor.
spring:datasource:url: jdbc:tc:postgresql:9.6.8:///test_databaseusername: userpassword: passwordjpa:hibernate:ddl-auto: create
Açıklaması şöyle
Have you noticed the tc suffix in the JDBC-connection string? That’s the magic that comes with the union of JUnit 5 and Test containers. The thing is that you don’t need any programmatic configurations at all! When the framework sees that url contains the tc suffix it runs all necessary Docker commands internally.
Elimizde şöyle bir service kodu olsun
@Service@RequiredArgsConstructorpublic class PersonCreateServiceImpl implements PersonCreateService {private final PersonValidateService personValidateService;private final PersonRepository personRepository;@Override@Transactionalpublic List<PersonDTO> createFamily(Iterable<String> firstNames, String lastName) {final var people = new ArrayList<PersonDTO>();firstNames.forEach(firstName -> people.add(createPerson(firstName, lastName)));return people;}@Override@Transactionalpublic PersonDTO createPerson(String firstName, String lastName) {personValidateService.checkUserCreation(firstName, lastName);final var createdPerson = personRepository.saveAndFlush(new Person().setFirstName(firstName).setLastName(lastName));return DTOConverters.toPersonDTO(createdPerson);}}
Bu service koduna H2 veri tabanı ile test yazsaydık şöyle olurdu. Burada repository sınıfı ve service sınıfı @Autowired ile aynen kullanılıyor. Service sınıfının kullandığı PersonValidateService ile mock'lanıyor. @AutoConfigureTestDatabase ile test için veri tabanı yaratılıyor.
@SpringBootTest(webEnvironment = WebEnvironment.NONE)@AutoConfigureTestDatabaseclass PersonCreateServiceImplSpringBootTest {@Autowiredprivate PersonRepository personRepository;@MockBeanprivate PersonValidateService personValidateService;@Autowiredprivate PersonCreateService personCreateService;@BeforeEachvoid init() {personRepository.deleteAll();}@Testvoid shouldCreateOnePerson() {final var people = personCreateService.createFamily(List.of("Simon"),"Kirekov");assertEquals(1, people.size());final var person = people.get(0);assertEquals("Simon", person.getFirstName());assertEquals("Kirekov", person.getLastName());assertTrue(person.getDateCreated().isBefore(ZonedDateTime.now()));}@Testvoid shouldRollbackIfAnyUserIsNotValidated() {doThrow(new ValidationFailedException("")).when(personValidateService).checkUserCreation("John", "Brown");assertThrows(ValidationFailedException.class, () -> personCreateService.createFamily(List.of("Matilda", "Vasya", "John"),"Brown"));assertEquals(0, personRepository.count());}}
Bu testi TestContainers ile çalışacak hale getirmek için şöyle yaparız. ActiveProfiles ile yaml dosyası kullanılır.
@SpringBootTest(webEnvironment = WebEnvironment.NONE)@Testcontainers@ActiveProfiles("test-containers")class PersonCreateServiceImplTestContainers {@Autowiredprivate PersonRepository personRepository;@MockBeanprivate PersonValidateService personValidateService;@Autowiredprivate PersonCreateService personCreateService;@BeforeEachvoid init() {personRepository.deleteAll();}@Testvoid shouldCreateOnePerson() {final var people = personCreateService.createFamily(List.of("Simon"),"Kirekov");assertEquals(1, people.size());final var person = people.get(0);assertEquals("Simon", person.getFirstName());assertEquals("Kirekov", person.getLastName());assertTrue(person.getDateCreated().isBefore(ZonedDateTime.now()));}@Testvoid shouldRollbackIfAnyUserIsNotValidated() {doThrow(new ValidationFailedException("")).when(personValidateService).checkUserCreation("John", "Brown");assertThrows(ValidationFailedException.class, () -> personCreateService.createFamily(List.of("Matilda", "Vasya", "John"),"Brown"));assertEquals(0, personRepository.count());}}
2. @Container Kullanımı
Repository sınıfı @Autowire ile test'e dahil edilir.
Örnek
Şöyle yaparız. Burada PostgreSQLContainer() sürümü veriliyor
// JUnit 5 example with Spring Boot >= 2.2.6@Testcontainers@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)public class ApplicationIT {@Containerpublic static PostgreSQLContainer container = new PostgreSQLContainer("postgres:11.1").withPassword("inmemory").withUsername("inmemory");@DynamicPropertySourcestatic void postgresqlProperties(DynamicPropertyRegistry registry) {registry.add("spring.datasource.url", container::getJdbcUrl);registry.add("spring.datasource.password", container::getPassword);registry.add("spring.datasource.username", container::getUsername);}...}
Eğer DataSource ta yaratmak istersek şöyle yaparız
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @Testcontainers @Import(Configuration.class) public abstract class BaseApiTest { @Container static final PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:10.9"); @DynamicPropertySource static void properties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", postgres::getJdbcUrl); registry.add("spring.datasource.username", postgres::getUsername); registry.add("spring.datasource.password", postgres::getPassword); } @TestConfiguration public static class Configuration { @Lazy @Bean("testSetupDataSource") public DataSource testInitDataSource() { PGSimpleDataSource ds = new PGSimpleDataSource(); ds.setUrl(postgres.getJdbcUrl()); ds.setDatabaseName(postgres.getDatabaseName()); ds.setUser(postgres.getUsername()); ds.setPassword(postgres.getPassword()); return ds; } } }
Örnek
Şöyle yaparız
@DataJdbcTest@Import(DatasourceConfig.class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @Testcontainers @DisplayName("Comment Repository Integration Tests With TestContainers") class CommentRepositoryTest { @Container static PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>(DockerImageName.parse("postgres:15.1")); @DynamicPropertySource static void overridePostgresProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", postgresContainer::getJdbcUrl); registry.add("spring.datasource.username", postgresContainer::getUsername); registry.add("spring.datasource.password", postgresContainer::getPassword); registry.add("spring.flyway.url", postgresContainer::getJdbcUrl); } @Autowired private CommentRepository commentRepository; ... }
Açıklaması şöyle
@DataJdbcTest focuses only on Data JDBC components.@Import(DatasourceConfig.class) provides JDBC auditing support.@AutoConfigureTestDatabase disables in-memory test databases with AutoConfigureTestDatabase.Replace.NONE value. Because we want to use real database instance instead of in-memory database.
Örnek
Şöyle yaparız. Liquibase veri tabanını test için doldurur
@Testcontainers@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes =
ContainerSpringAfter226Test.class)@EnableAutoConfigurationpublic class ContainerSpringAfter226Test {@Containerpublic static PostgreSQLContainer postgreSQLContainer =
SharedPostgresSQLContainer.getInstance().withDatabaseName("dbname").withUsername("user").withPassword("password");@DynamicPropertySourcepublic static void postgreSQLProperties(DynamicPropertyRegistry registry) {registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);registry.add("spring.datasource.username", postgreSQLContainer::getUsername);registry.add("spring.datasource.password", postgreSQLContainer::getPassword);registry.add("spring.liquibase.url", postgreSQLContainer::getJdbcUrl);registry.add("spring.liquibase.user", postgreSQLContainer::getUsername);registry.add("spring.liquibase.password", postgreSQLContainer::getPassword);registry.add("spring.liquibase.change-log",
() -> "classpath:/db/changelog/db.changelog-master.xml");}...}
Örnek
Şöyle yaparız
@TestConfiguration public class PostgresSQLTestContainerConfig extends PostgreSQLContainer<PostgresSQLTestContainerConfig> { private static final String DOCKER_IMAGE_VERSION = "postgres:latest"; private static final PostgresSQLTestContainerConfig POSTGRES_SQL_TEST_CONTAINER = new PostgresSQLTestContainerConfig().withReuse(true); static { POSTGRES_SQL_TEST_CONTAINER.start(); System.setProperty("spring.datasource.url", POSTGRES_SQL_TEST_CONTAINER.getJdbcUrl()); System.setProperty("spring.datasource.username", POSTGRES_SQL_TEST_CONTAINER.getUsername()); System.setProperty("spring.datasource.password", POSTGRES_SQL_TEST_CONTAINER.getPassword()); } public PostgresSQLTestContainerConfig() { super(DOCKER_IMAGE_VERSION); } @Override public void stop() { // do nothing, JVM handles shut down } }
Hiç yorum yok:
Yorum Gönder