testcontainer initializationError while 运行 一个测试套件

testcontainer initializationError while running a test suite

我有多个测试 classes 运行 相同 docker-compose with testcontainer.

虽然每个测试在单独执行时都通过了,但套件失败并显示 initializationError

这是第二次测试期间发生的堆栈跟踪的相关部分。 ./gradlew e2e:test -i

io.foo.e2e.AuthTest > initializationError FAILED
    org.testcontainers.containers.ContainerLaunchException: Container startup failed
        at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:330)
        at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:311)
        at org.testcontainers.containers.DockerComposeContainer.startAmbassadorContainers(DockerComposeContainer.java:331)
        at org.testcontainers.containers.DockerComposeContainer.start(DockerComposeContainer.java:178)
        at io.foo.e2e.bases.BaseE2eTest$Companion.beforeAll$e2e(BaseE2eTest.kt:62)
        at io.foo.e2e.bases.BaseE2eTest.beforeAll$e2e(BaseE2eTest.kt)
       ...

        Caused by:
        org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
            at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:88)
            at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:323)
            ... 83 more

            Caused by:
            org.testcontainers.containers.ContainerLaunchException: Could not create/start container
                at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:497)
                at org.testcontainers.containers.GenericContainer.lambda$doStart[=11=](GenericContainer.java:325)
                at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
                ... 84 more

                Caused by:
                org.testcontainers.containers.ContainerLaunchException: Aborting attempt to link to container btraq5fzahac_worker_1 as it is not running
                    at org.testcontainers.containers.GenericContainer.applyConfiguration(GenericContainer.java:779)
                    at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:359)
                    ... 86 more

在我看来,第二个测试不会等待第一个关闭之前的容器。

这里是所有测试继承的基础class。它负责启动容器。

open class BaseE2eTest {

    ...

    companion object {
        const val A = "containera_1"
        const val B = "containerb_1"
        const val C = "containerc_1"

        val dockerCompose: KDockerComposeContainer by lazy {
            defineDockerCompose()
                .withLocalCompose(true)
                .withExposedService(A, 8080, Wait.forListeningPort())
                .withExposedService(B, 8081)
                .withExposedService(C, 5672, Wait.forListeningPort())
        }

        class KDockerComposeContainer(file: File) : DockerComposeContainer<KDockerComposeContainer>(file)

        private fun defineDockerCompose() = KDockerComposeContainer(File("../docker-compose.yml"))

        @BeforeAll
        @JvmStatic
        internal fun beforeAll() {
            dockerCompose.start()
        }

        @AfterAll
        @JvmStatic
        internal fun afterAll() {
            dockerCompose.stop()
        }
    }
}
docker-compose version 1.27.4, build 40524192
testcontainer 1.15.2
testcontainers:junit-jupiter:1.15.2

看了this talk之后,我意识到我用 Junit5 的 testcontainers 实例化方法是错误的。

这是工作代码:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
open class BaseE2eTest {

    ...

    val A = "containera_1"
    val B = "containerb_1"
    val C = "containerc_1"

    val dockerCompose: KDockerComposeContainer by lazy {
        defineDockerCompose()
            .withLocalCompose(true)
            .withExposedService(A, 8080, Wait.forListeningPort())
            .withExposedService(B, 8081)
            .withExposedService(C, 5672, Wait.forListeningPort())
    }

    class KDockerComposeContainer(file: File) : DockerComposeContainer<KDockerComposeContainer>(file)

    private fun defineDockerCompose() = KDockerComposeContainer(File("../docker-compose.yml"))

    @BeforeAll
    fun beforeAll() {
        dockerCompose.start()
    }

    @AfterAll
    fun afterAll() {
        dockerCompose.stop()
    }
}

现在测试套件通过了。