How to use Testcontainers and Inject servcies in Quarkus?

Viewed 35

I try to migrate my Integration Test Class to use @Testcontainers.

Original Test Class was like

@QuarkusTest
class GameResourceTest {

    @Inject
    TeamService teamService;

    @Test
    void shouldLeadTheRankLadder() {
     teamService.doCrazyStuff();  // PASS

After rewrite it looks like this

@Testcontainers
class GameResourceTest {

    @Container
    private MariaDBContainer mariaDBContainer = new MariaDBContainer("mariadb:10.5.16").withDatabaseName("test").withUsername("test").withPassword("test");
    
    @Inject
    TeamService teamService;

    @Test
    void test() {
     assertTrue(mariaDBContainer.isRunning()); // PASS
    }

    @Test
    void shouldLeadTheRankLadder() {
     teamService <-----------------------IS NULL HERE

So after removing the @QuarkusTest annoation, dependency injection of my service not work anymore.

How to use Testcontainers and Dependency Injection here?

2 Answers

The proper way to integrate Testcontainers with Quarkus is to use launch a container via a QuarkusTestResourceLifecycleManager.

See this example class that does exactly that.

I should also mentioned that dependency injection does work in @QuarkusTest tests

The best way to use Quarkus with Testcontainers is to use a QuarkusTestResourceLifecycleManager guide.

Quarkus Kotlin example:


class DatabaseTestLifeCycleManager : QuarkusTestResourceLifecycleManager {
    private val postgresDockerImage = DockerImageName.parse("postgres:latest")

    override fun start(): MutableMap<String, String>? {
        val container = startPostgresContainer()

        return mutableMapOf(
            "quarkus.datasource.username" to container.username,
            "quarkus.datasource.password" to container.password,
            "quarkus.datasource.jdbc.url" to container.jdbcUrl
        )
    }

    private fun startPostgresContainer(): PostgreSQLContainer<out PostgreSQLContainer<*>> {
        val container = PostgreSQLContainer(postgresDockerImage)
            .withDatabaseName("dataBaseName")
            .withUsername("username")
            .withPassword("password")
        container.start()
        return container
    }

    override fun stop() {
        // close container
    }
}

And in your test, annotate it with @QuarkusTestResource

Example:

@QuarkusTest
@QuarkusTestResource(DatabaseTestLifeCycleManager::class, restrictToAnnotatedClass = true)
class MyTest {

    @Inject
    lateinit var dependency: InjectableDependency

    @InjectMock
    lateinit var mockedDependency: AnotherInjectableDependency
}
Related