5 Nisan 2023 Çarşamba

Testcontainers PostgreSQLContainer Sınıfı

Giriş
Şu satırı dahil ederiz
import org.testcontainers.containers.PostgreSQLContainer;
Üç tane bağımlılık gerekiyor. Açıklaması şöyle
1. org.testcontainers:testcontainers
includes core packages.
2. org.testcontainers:postgresql
includes PostgreSQL-specific packages. This dependency depends on database which your application is using. You will find the list of supported databases here.
3. org.testcontainers:junit-jupiter
integrates JUnit with Testcontainers.
Maven
Ş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>
Gradle
Şöyle yaparız
dependencies {
 ...
 testImplementation 'org.testcontainers:testcontainers'
 testImplementation 'org.testcontainers:postgresql' 
 testImplementation 'org.testcontainers:junit-jupiter'
 ...
}

dependencyManagement {
 imports {
  mavenBom "org.testcontainers:testcontainers-bom:1.17.6"
 }
}
1. DriverManager.getConnection İle Kullanımı
PostgreSQLContainer nesnesi yaratıldıktan sonra JDBC ile iş yapacaksak DriverManager nesnesini kullanarak JDBC Connection elde etmek lazım. 

Örnek - URL + UserName + Password
DriverManager.getConnection() çağrısına kullanıcı adı ve şifre geçeceksek şöyle yaparız
DockerImageName POSTGRES_IMAGE =
  DockerImageName.parse("debezium/example-postgres:1.7")
  .asCompatibleSubstituteFor("postgres");

PostgreSQLContainer container = new PostgreSQLContainer<>(POSTGRES_IMAGE)
  .withDatabaseName("postgres")
  .withUsername("postgres")
  .withPassword("postgres")
  .withConnectTimeoutSeconds(300)
  .withStartupTimeoutSeconds(300)
  .withStartupAttempts(5)
  .withCreateContainerCmdModifier(createContainerCmd -> {...})

container.start();

 try (Connection connection = DriverManager.getConnection(container.getJdbcUrl(), 
                                                          container.getUsername(),
                                                          container.getPassword())) {
  connection.setSchema("inventory");
  try (Statement statement = connection.createStatement()) {
    ...
  }
}
Örnek - URL İçinde UserName ve Password
Eğer DriverManager.getConnection() ile sadece URL kullanacaksak şöyle yapmak gerekiyor
String jdbcUrl = container.getJdbcUrl() + "&user=" + container.getUsername() +
                                  "&password=" + container.getPassword();
// Output
jdbc:postgresql://localhost:52135/test?loggerLevel=OFF&user=test&password=test

 2. PostgreSQLContainer Metodlar
Çok fazla metod var. Bazı örnekler aşağıda

getDriverClassName metodu
Örnek - Eski Spring Kodu
Şöyle yaparız.  Yeni Spring ile artık @DynamicPropertySource anotasyonuna gerek yok
@Testcontainers
@ContextConfiguration(classes = {PersistenceConfig.class})
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class StudentRepositoryJpaIT extends StudentRepositoryTest {

  @Container
  public static PostgreSQLContainer container = new PostgreSQLContainer("postgres:latest")
    .withDatabaseName("students_db")
    .withUsername("sa")
    .withPassword("sa");


  @DynamicPropertySource
  public static void overrideProperties(DynamicPropertyRegistry registry){
    registry.add("spring.datasource.url", container::getJdbcUrl);
    registry.add("spring.datasource.username", container::getUsername);
    registry.add("spring.datasource.password", container::getPassword);
    registry.add("spring.datasource.driver-class-name", container::getDriverClassName);
  }
  ...
}
getFirstMappedPort
Örnek
Şöyle yaparız
Integer hostPort = container.getFirstMappedPort();
getHost metodu
Örnek
Şöyle yaparız
String host = container.getHost()
getJdbcUrl metodu
Şöyle yaparız
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;

public class PostgresIntegrationTest {
  @Container
  private static final PostgreSQLContainer<?> postgresContainer =
    new PostgreSQLContainer<>("postgres:latest");

  @Test
  void testDatabaseConnection() {
    // Get database connection properties from the container instance
    String jdbcUrl = postgresContainer.getJdbcUrl();
    String username = postgresContainer.getUsername();
    String password = postgresContainer.getPassword();

    // Perform database tests using the connection properties
    // ...
  }
}
getMappedPort metodu
Açıklaması şöyle
You cannot choose which actual port is used on the host machine. TestContainers chooses one automatically and makes it accessible through getMappedPort(containerPort) method on the container instance. You can also use getFirstMappedPort() if you only have one.
Örnek
Şöyle yaparız
Integer hostPort = container.getMappedPort(8080);
Örnek
Şöyle yaparız. PostgreSQLContainer.POSTGRESQL_PORT değişkenin değeri 5432
Integer hostPort = container.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT);
withCommand metodu
Örnek
Şöyle yaparız
public static PostgreSQLContainer container = new PostgreSQLContainer<>("postgres:12.1")
  .withCommand("postgres -c max_prepared_transactions=10")
  .withCommand("postgres -c max_connections=500");
Aynı şeyi şöyle yaparız
public static PostgreSQLContainer container = new PostgreSQLContainer<>("postgres:12.1")
  .withCommand("postgres -c max_prepared_transactions=10 -c max_connections=500");
withTmpFs metodu
Örnek
Şöyle yaparız. Burada PGDATA ortam değişkeni de /var/lib/postgresql/data olarak değiştiriliyor ama bence gerek yok. Çünkü varsayılan değer zaten böyle
var container = PostgreSQLContainer(postgresDockerImage)
  .withDatabaseName("dataBaseName")
  .withUsername("username")
  .withPassword("password")
  .withEnv(mapOf("PGDATA" to "/var/lib/postgresql/data"))
  .withTmpFs(mapOf("/var/lib/postgresql/data" to "rw"))

withUsername metodu
Şöyle yaparız
@Container
private static final PostgreSQLContainer<?> postgresContainer =
  new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest"))
    .withDatabaseName("mydb")
    .withUsername("user")
    .withPassword("password");


Hiç yorum yok:

Yorum Gönder