1

I intend to test database access utilizing Testcontainer (version 1.15.2) with Kotlin 1.4.31 and I have a test class...

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.MediaType
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.springframework.test.web.reactive.server.WebTestClient
import org.testcontainers.containers.PostgreSQLContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
import java.time.Instant
import java.util.*

//@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
@Testcontainers
@ExtendWith(SpringExtension::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
//class PostgresTcTest(var dao: GenericJpaDao<Declaration>, var webTestClient: WebTestClient) {
class PostgresTcTest {
    @Autowired
    lateinit var webTestClient: WebTestClient
    @Autowired
    lateinit var dao: GenericJpaDao<Declaration>
//    val POSTGRES_IMAGE = DockerImageName.parse("postgres:13.2-alpine")
//
//    val container by lazy { PostgreSQLContainer<Nothing>(POSTGRES_IMAGE) }

    companion object {

        @Container
        val container = PostgreSQLContainer<Nothing>("postgres:13.2-alpine")/*.apply {
            withDatabaseName("testdb")
            withUsername("duke")
            withPassword("s3crEt")
        }*/

        @JvmStatic
        @DynamicPropertySource
        fun properties(registry: DynamicPropertyRegistry) {
            registry.add("spring.datasource.url", container::getJdbcUrl);
            registry.add("spring.datasource.password", container::getPassword);
            registry.add("spring.datasource.username", container::getUsername);
        }
    }
}

...but I always get an exception:

Driver org.testcontainers.jdbc.ContainerDatabaseDriver claims to not accept jdbcUrl, jdbc:postgresql://localhost:55017/test?loggerLevel=OFF

I have an application.yaml containing:

spring:
  datasource:
    driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
    url: jdbc:tc:postgresql:13.2:///testdb?TC_INITSCRIPT=tc_initscript_postgresql.sql
    username: duke
    password: s3crEt
  jpa:
    database-platform: org.hibernate.dialect.PostgreSQL95Dialect
    hibernate:
      ddl-auto: create-drop

I wonder why TestContainers is vainly looking for jdbc:postgresql although I put jdbc:tc:postgresql in application.yaml

I would prefer using constructor autowiring but I didn't get it because Kotlin always complains:

org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [de.xxx.dao.GenericJpaDao<de.xxx.model.Declaration> dao] in constructor [public de.xxx.db.PostgresTcTest(de.xxx.dao.GenericJpaDao<de.xxx.model.Declaration>,org.springframework.test.web.reactive.server.WebTestClient)].

    at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameter(ExecutableInvoker.java:200)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameters(ExecutableInvoker.java:183)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:74)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestClassConstructor(ClassBasedTestDescriptor.java:342)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateTestClass(ClassBasedTestDescriptor.java:289)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateTestClass(ClassTestDescriptor.java:79)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:267)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$2(ClassBasedTestDescriptor.java:259)

I can't achieve getting an instance of GenericJpaDao and WebTestClient neither by constructor autowiring nor by using @Autowired at the field.


Answer according to the WebTestClient: This can be achieved by using @AutoConfigureWebTestClient

du-it
  • 2,561
  • 8
  • 42
  • 80

1 Answers1

1

You don't need to set driver-class-name.

Remove this from application.properties

spring:
  datasource:
    url: jdbc:tc:postgresql:13.2:///testdb?TC_INITSCRIPT=tc_initscript_postgresql.sql
    username: duke
    password: s3crEt
  jpa:
    database-platform: org.hibernate.dialect.PostgreSQL95Dialect
    hibernate:
      ddl-auto: create-drop
Simon Martinelli
  • 34,053
  • 5
  • 48
  • 82
  • This is correct. But can you tell me why Testcontainers is not using url, username and password from application.yaml? When I debug the app all of them are set to 'test'. – du-it Mar 17 '21 at 07:42
  • Because you are overriding them in the method annotated with @DynamicPropertySource. And hthis is correct – Simon Martinelli Mar 17 '21 at 08:02