When i run many parallell tests with ktor testAppl...
# ktor
a
When i run many parallell tests with ktor testApplication i always hit the 10 second timeout on some tests no matter what i configure. I use junit 5, anyone else had this problem?
a
Can you please share the code of the test?
a
Sure. This is one example:
Copy code
@Execution(SAME_THREAD)
class InvoicingInvoiceDateTest : WithPostgreSQL(shouldPopulate = false) {
    private val configuration = createApplicationConfig(RuntimeEnvironment("local"))
    private lateinit var finalConfig: Config

    @BeforeEach
    fun setup() =
        runTest(
            timeout = 300.seconds,
        ) {
            finalConfig =
                configuration.copy(
                    database =
                        DatabaseConfig(
                            userName = postgres.username,
                            password = Masked(postgres.password),
                            host = postgres.host,
                            readonlyHost = postgres.host,
                            port = postgres.getMappedPort(5432),
                            db = postgres.databaseName,
                            schema = schema,
                        ),
                )
        }

    @Test
    fun `preview one time plan`() =
        runTest(
            timeout = 300.seconds,
        ) {
            val firstMonth =
                now()
                    .withDayOfMonth(1)
                    .withHour(5)
            val company =
                readWrite.withTransaction {
                    InvoicingCompanyGenerator().generateCompany(
                        planSettings =
                            InvoicePlanSettingsSeed(
                                interval = NONE,
                                oneTimeDate = firstMonth,
                            ),
                    )
                }

            testApplication {
                application {
                    mainModule(
                        applicationConfig = finalConfig,
                        shouldSetRoutes = true,
                    )

                    val invoicingService by instance<InvoicingService>()

                    val planSettings =
                        readOnly.withSession {
                            invoicingService
                                .showPlanSettings(
                                    companyId = company.companyId,
                                    planId = company.sharedExpensesPlanId,
                                ).revisions
                                .first()
                        }
                    val dueDate = planSettings.dueDate.toLong()

                    val previews =
                        readOnly.withSession {
                            invoicingService.preview(
                                companyId = company.companyId,
                                planId = company.sharedExpensesPlanId,
                                at = firstMonth,
                            )
                        }

                    previews.size.shouldBe(400, firstMonth.toGMTDate().toString())
                    previews.forEach {
                        it.invoiceDate.toLocalDate() shouldBe firstMonth.toLocalDate()
                        it.dueDate.toLocalDate() shouldBe
                            firstMonth
                                .plusDays(dueDate)
                                .toLocalDate()
                    }
                }
            }
        }
WithPostgreSQL produces a schema for the test. Transactions and sessions run on IO. All functions are suspended.
SAME_THREAD is used to avoid the timeout. Many parallell tests slow everything down so thats when i see the exception.
Ive tried setting a @Timeout and also
Copy code
"-Dkotlinx.coroutines.test.default_timeout=300s"
but none of this works.
a
It's difficult to determine the root cause just by looking at this code. To isolate the issue, I recommend removing parts of the code step by step.
a
Copy code
@Test
fun `do the thing`() =
    runTest(
        timeout = 300.seconds,
    ) {
        testApplication {
            application {
                delay(20000)
            }
        }
    }
This gives the same result
Timed out waiting for 10000 ms kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 10000 ms at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt:42) at solibo.economy.invoicing.InvoicingDueDateTest$do the thing$1$1$1.invokeSuspend(InvoicingDueDateTest.kt:449) at io.ktor.server.engine.EmbeddedServer$toDynamicModuleOrNull$1.invokeSuspend(EmbeddedServerJvm.kt:431) at io.ktor.server.application.ApplicationModules_jvmKt$LoadSequentially$1.loadModules(ApplicationModules.jvm.kt:75) at io.ktor.server.engine.EmbeddedServer$instantiateAndConfigureApplication$1$1.invokeSuspend(EmbeddedServerJvm.kt:385) at io.ktor.server.engine.EmbeddedServer$instantiateAndConfigureApplication$1.invokeSuspend(EmbeddedServerJvm.kt:384) at io.ktor.server.engine.EmbeddedServer$avoidingDoubleStartup$1.invokeSuspend(EmbeddedServerJvm.kt:450) at io.ktor.server.testing.TestApplication.start(TestApplication.kt:103) at io.ktor.server.testing.TestApplicationKt.runTestApplication(TestApplication.kt:537) at io.ktor.server.testing.TestApplicationKt$testApplication$1.invokeSuspend(TestApplication.kt:517) at io.ktor.test.dispatcher.TestCommonKt$runTestWithRealTime$1.invokeSuspend(TestCommon.kt:40) at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$1.invokeSuspend(TestBuilders.kt:317) Caused by: kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 10000 ms at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:189) at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:157) at kotlinx.coroutines.EventLoopImplBase$DelayedRunnableTask.run(EventLoop.common.kt:505) at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:263) at kotlinx.coroutines.DefaultExecutor.run(DefaultExecutor.kt:105) at java.base/java.lang.Thread.run(Thread.java:1583)
a
It's a default 10-second time limit waiting for the application modules to start up. You can configure it by changing the
ktor.application.startupTimeoutMillis
property in the configuration:
Copy code
testApplication {
    environment {
        config = MapApplicationConfig(
            listOf("ktor.application.startupTimeoutMillis" to "300000")
        )
    }
    application {
        delay(20000)
    }
}
a
Nice, will check. Is this documented anywhere?
a
I don't think so
a
Looked for it earlier but no success 😄
That did the trick, is there any way to specify defaults for the environment?
a
Unfortunately, there is no such way, but you can define a wrapper function for the
testApplication
function where the timeout will be set.
a
Yupp, thats what i did. No biggie. Thanks for the help!