Fix HttpTimeout not respecting test dispatchers in runTest - #5512
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe PR captures the current coroutine context at the start of HttpTimeout's send handler and applies per-request timeouts inside a new CoroutineScope created from that context. It also adds a test verifying request timeout behavior with virtual time in runTest. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
94540ad to
7a37528
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
ktor-client/ktor-client-mock/common/test/HttpTimeoutVirtualTimeTest.kt (1)
19-36: Consider usinguse {}for guaranteed client cleanup.If an unexpected exception occurs (e.g., a different exception type than
HttpRequestTimeoutException),client.close()will be skipped. Using theuse {}pattern ensures cleanup regardless of test outcome.♻️ Suggested refactor
`@Test` fun `request timeout fires using virtual time in runTest`() = runTest(timeout = 5.seconds) { - val client = HttpClient(MockEngine) { + HttpClient(MockEngine) { engine { addHandler { awaitCancellation() } } install(HttpTimeout) { requestTimeoutMillis = 60_000 } - } - - assertFailsWith<HttpRequestTimeoutException> { - client.get("http://localhost/test") + }.use { client -> + assertFailsWith<HttpRequestTimeoutException> { + client.get("http://localhost/test") + } } - - client.close() }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ktor-client/ktor-client-mock/common/test/HttpTimeoutVirtualTimeTest.kt` around lines 19 - 36, The test creates an HttpClient (HttpClient(MockEngine) { ... }) and calls client.close() manually, which can be skipped if an unexpected exception is thrown; change this to use the Kotlin use { } pattern so the HttpClient is always closed — locate the test function request timeout fires using virtual time in runTest and wrap the HttpClient instantiation (the HttpClient(MockEngine) block that defines engine { addHandler { awaitCancellation() } } and installs HttpTimeout) with use { client -> ... } and move the client.get call and assertion inside the use block so cleanup is guaranteed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@ktor-client/ktor-client-mock/common/test/HttpTimeoutVirtualTimeTest.kt`:
- Around line 19-36: The test creates an HttpClient (HttpClient(MockEngine) {
... }) and calls client.close() manually, which can be skipped if an unexpected
exception is thrown; change this to use the Kotlin use { } pattern so the
HttpClient is always closed — locate the test function request timeout fires
using virtual time in runTest and wrap the HttpClient instantiation (the
HttpClient(MockEngine) block that defines engine { addHandler {
awaitCancellation() } } and installs HttpTimeout) with use { client -> ... } and
move the client.get call and assertion inside the use block so cleanup is
guaranteed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b0444573-89cb-4159-9a8d-2fd143e46eb8
📒 Files selected for processing (2)
ktor-client/ktor-client-core/common/src/io/ktor/client/plugins/HttpTimeout.ktktor-client/ktor-client-mock/common/test/HttpTimeoutVirtualTimeTest.kt
7a37528 to
1ae285b
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
ktor-client/ktor-client-core/common/test/HttpTimeoutVirtualTimeTest.kt (1)
19-35: Make client cleanup unconditional.If the assertion path changes or fails unexpectedly,
client.close()may be skipped. Wrap usage intry/finallyto guarantee cleanup.♻️ Suggested refactor
val client = HttpClient(MockEngine) { engine { addHandler { awaitCancellation() } } install(HttpTimeout) { requestTimeoutMillis = 60_000 } } - assertFailsWith<HttpRequestTimeoutException> { - client.get("http://localhost/test") - } - - client.close() + try { + assertFailsWith<HttpRequestTimeoutException> { + client.get("http://localhost/test") + } + } finally { + client.close() + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ktor-client/ktor-client-core/common/test/HttpTimeoutVirtualTimeTest.kt` around lines 19 - 35, The test instantiates HttpClient(MockEngine) and asserts a timeout but currently calls client.close() after the assertion which can be skipped on failure; wrap the client usage in a try/finally so that the HttpClient created in the HttpClient(MockEngine) block is always closed in the finally block (ensure the awaitCancellation handler, install(HttpTimeout) configuration and the client.get("http://localhost/test") call remain the same, only move client.close() into finally).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ktor-client/ktor-client-core/common/test/HttpTimeoutVirtualTimeTest.kt`:
- Line 18: Rename the test function
testRequestTimeoutRespectsVirtualTimeInRunTest to use a backticked, descriptive
test name per guidelines; change the declaration of fun
testRequestTimeoutRespectsVirtualTimeInRunTest() = runTest(timeout = 5.seconds)
to a backtick-named Kotlin test such as fun `request timeout respects virtual
time in runTest`() = runTest(timeout = 5.seconds) so the test file follows the
`/test/**/*.kt` naming convention and remains runnable.
---
Nitpick comments:
In `@ktor-client/ktor-client-core/common/test/HttpTimeoutVirtualTimeTest.kt`:
- Around line 19-35: The test instantiates HttpClient(MockEngine) and asserts a
timeout but currently calls client.close() after the assertion which can be
skipped on failure; wrap the client usage in a try/finally so that the
HttpClient created in the HttpClient(MockEngine) block is always closed in the
finally block (ensure the awaitCancellation handler, install(HttpTimeout)
configuration and the client.get("http://localhost/test") call remain the same,
only move client.close() into finally).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0357fb09-ced9-43d5-acd9-c5bf9826187f
📒 Files selected for processing (2)
ktor-client/ktor-client-core/common/src/io/ktor/client/plugins/HttpTimeout.ktktor-client/ktor-client-core/common/test/HttpTimeoutVirtualTimeTest.kt
🚧 Files skipped from review as they are similar to previous changes (1)
- ktor-client/ktor-client-core/common/src/io/ktor/client/plugins/HttpTimeout.kt
Bruce Hamilton (bjhham)
left a comment
There was a problem hiding this comment.
Thank you for the fix 🙏
Subsystem
Client
Motivation
#4720
Solution
Capture the caller's coroutine context before launching the timeout and use it when creating the
CoroutineScopeforapplyRequestTimeout, so that test dispatchers (virtual time) are respected.