-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
Summary
runTest
is hard coded to advance time and it would be nice to make that configurable.
Use case
I am writing tests that involve the a Postgres database and time. To avoid waiting the actual amount of time, I used a runTest {}
based test. The problem is that my implementation of the database is with jasync suspending connection. During the test, a jasync call runs and a separate thread is running to handle the request. From the TestScope's point of view, there are no more coroutines to run. So, it advances time and hits a withTimout
I have above the jasync command. I understand that a lot of the time the workRunner
is really nice. I would like to have the option of it only running current tasks instead of incrementing the time automatically.
This is the section that is firing.
val workRunner = launch(CoroutineName("kotlinx.coroutines.test runner")) {
while (true) {
// This `tryRunNextTaskUnless` automatically advances `currentTime`
val executedSomething = testScheduler.tryRunNextTaskUnless { !isActive }
if (executedSomething) {
/** yield to check for cancellation. On JS, we can't use [ensureActive] here, as the cancellation
* procedure needs a chance to run concurrently. */
yield()
} else {
// waiting for the next task to be scheduled, or for the test runner to be cancelled
testScheduler.receiveDispatchEvent()
}
}
}
Example real life failing test case
@Test
fun `should notify when your replacement doesn't show up`() = testContext.withLogic {
schedule("adalovelace", "1991-08-26T07:57:08.123456Z")
// Timeout here because jasync processing is unknown to runTest
delay(12.hours())
notifications.sent("adalovelace", "Your replacement hasn't arrived yet.")
}
Example simple failing test case
@Test
fun `should allow manually updating the clock`() {
val suspendingConnection = PostgreSQLConnectionBuilder
.createConnectionPool("jdbc:postgresql://$host:$port/$databaseName?user=$username&password=$password")
.asSuspending
runTest {
withTimeout(1_000) {
suspendingConnection.sendQuery("SELECT 1;")
}
}
}
I can try to create a project to demonstrate the problem if this isn't clear enough. Just let me know.
The Shape of the API
I am not quite sure on how we can replace this. I mean it would be nice if there was just another dispatcher like StandardDispatcher
that had this behavior. Something like PauseDispatcher
, ManualDispatcher
, or something like that. I don't think that would allow you to replace the code in question. I think it would require a larger change.