Tags: kotest/kotest
Tags
Add module-factory support to KoinExtension (#6006) (#6138) Mitigates #6006. ## Background `KoinExtension` captured `Module` *instances* at construction (`private val modules: List<Module>`) and fed the same instances to `startKoin { modules(modules) }` on every test. Since Kotest v6 exposes a spec's extensions as a property (`open val extensions: List<Extension>`) rather than v5's re-evaluated `fun extensions()`, those module instances now live for the spec's whole lifetime. When a test mutates the Koin context via `KoinTest.declare`, reusing the same `Module` instance can leak singleton state into later tests: Koin caches instances on the `SingleInstanceFactory`s held by the module, and `declare()` orphans a factory whose cached singleton survives `stopKoin()`/`startKoin()`. This is fundamentally the upstream Koin bug [InsertKoinIO/koin#2412](InsertKoinIO/koin#2412); Kotest v6 just makes it far easier to hit. We're pinned to Koin 4.1.0 (4.2.x needs Kotlin 2.3.x KLIB ABI), and the upstream bug spans 3.x–4.2.1, so a version bump isn't a fix. ## Change Add an opt-in `KoinExtension` constructor that accepts a module **factory** (`() -> List<Module>`), invoked on each Koin start so every test gets fresh module instances (and therefore fresh singletons), restoring v5-like isolation regardless of the upstream bug: ```kotlin // myModule() builds a fresh Module each call extension(KoinExtension { listOf(myModule()) }) ``` - The previous primary constructor `(List<Module>, Provider?, KoinLifecycleMode)` is preserved as a public secondary constructor, so all existing instance-based usage and binary compatibility are unaffected (API diff is purely additive). - New regression test `KoinExtensionModuleFactoryTest` reproduces the `declare()` scenario and asserts the next test sees a clean singleton. - Documents the workaround in `documentation/docs/extensions/koin.md`. ## Verification - `:kotest-extensions-koin:jvmTest` — passes (new test + existing Koin tests) - `apiDump` regenerated and committed; `apiCheck` passes The underlying defect should ultimately be fixed in Koin (koin#2412); this is a pragmatic mitigation for v6 users in the meantime. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Alfonso Ristorato <73172255+alfonsoristorato@users.noreply.github.com>
complete custom styles DSL (#6179) <!-- If this PR updates documentation, please update all relevant versions of the docs, see: https://github.com/kotest/kotest/tree/master/documentation/versioned_docs The documentation at https://github.com/kotest/kotest/tree/master/documentation/docs is the documentation for the next minor or major version _TO BE RELEASED_ --> #6162
Update dependency io.projectreactor.tools:blockhound to v1.0.17.RELEA… …SE (#6164) This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [io.projectreactor.tools:blockhound](https://redirect.github.com/reactor/BlockHound) | `1.0.16.RELEASE` → `1.0.17.RELEASE` |  |  | --- ### Release Notes <details> <summary>reactor/BlockHound (io.projectreactor.tools:blockhound)</summary> ### [`v1.0.17.RELEASE`](https://redirect.github.com/reactor/BlockHound/releases/tag/1.0.17.RELEASE) [Compare Source](https://redirect.github.com/reactor/BlockHound/compare/1.0.16.RELEASE...1.0.17.RELEASE) ### What's Changed #### 🧹 Housekeeping - Upgrade to `Gradle` `9.5.1` ([#​571](https://redirect.github.com/reactor/BlockHound/issues/571), [#​573](https://redirect.github.com/reactor/BlockHound/issues/573), [#​580](https://redirect.github.com/reactor/BlockHound/issues/580), [#​583](https://redirect.github.com/reactor/BlockHound/issues/583)) [@​violetagg](https://redirect.github.com/violetagg) and @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) #### 📦 Dependency updates - Bump `actions/checkout` from `6.0.2` to `6.0.3` ([#​590](https://redirect.github.com/reactor/BlockHound/issues/590)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump `net.bytebuddy:byte-buddy` from `1.18.3` to `1.18.10` ([#​554](https://redirect.github.com/reactor/BlockHound/issues/554), [#​563](https://redirect.github.com/reactor/BlockHound/issues/563), [#​566](https://redirect.github.com/reactor/BlockHound/issues/566), [#​576](https://redirect.github.com/reactor/BlockHound/issues/576), [#​586](https://redirect.github.com/reactor/BlockHound/issues/586), [#​589](https://redirect.github.com/reactor/BlockHound/issues/589)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump `com.gradleup.shadow` from `9.4.0` to `9.4.2` ([#​574](https://redirect.github.com/reactor/BlockHound/issues/574), [#​585](https://redirect.github.com/reactor/BlockHound/issues/585)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump `release-drafter/release-drafter` from `6.2.0` to `7.3.1` ([#​568](https://redirect.github.com/reactor/BlockHound/issues/568), [#​569](https://redirect.github.com/reactor/BlockHound/issues/569), [#​570](https://redirect.github.com/reactor/BlockHound/issues/570), [#​572](https://redirect.github.com/reactor/BlockHound/issues/572), [#​577](https://redirect.github.com/reactor/BlockHound/issues/577), [#​581](https://redirect.github.com/reactor/BlockHound/issues/581), [#​582](https://redirect.github.com/reactor/BlockHound/issues/582), [#​584](https://redirect.github.com/reactor/BlockHound/issues/584)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump `org.junit.jupiter:juni 8000 t-jupiter-api` from `5.14.2` to `5.14.4` ([#​562](https://redirect.github.com/reactor/BlockHound/issues/562), [#​578](https://redirect.github.com/reactor/BlockHound/issues/578)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump `de.undercouch.download` from `5.6.0` to `5.7.0` ([#​561](https://redirect.github.com/reactor/BlockHound/issues/561)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump `org.assertj:assertj-core` from `3.27.6` to `3.27.7` ([#​559](https://redirect.github.com/reactor/BlockHound/issues/559)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump `actions/setup-java` from `5.1.0` to `5.2.0` ([#​556](https://redirect.github.com/reactor/BlockHound/issues/556)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - "before 3am on the first day of the month" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/kotest/kotest). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDIuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI0Mi4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Make flaky "throws FileNotFoundException for some time" eventually te… …st deterministic (#6149) ## Problem `EventuallyTest > "pass tests that throws FileNotFoundException for some time"` is flaky on CI: ``` EventuallyTest[jvm] > pass tests that throws FileNotFoundException for some time FAILED org.opentest4j.AssertionFailedError at Undispatched.kt:66 ``` It ran an `eventually` block for 50ms at a 10ms interval and asserted `iterations.shouldBeBetween(3, 7)` ("approx 5 iterations"). The iteration count is wall-clock dependent, so on a loaded runner scheduling jitter (GC, CPU contention) pushes it outside `[3, 7]` and the test fails intermittently. Observed failing in an unrelated PR's CI run. ## Fix Drive the retry loop by a fixed **attempt count** instead of elapsed time: the block throws a transient `FileNotFoundException` for the first few attempts and then succeeds, and the test asserts the exact attempt count. This exercises the same behaviour the test was written for — `eventually` keeps retrying through transient exceptions and then passes — but is fully deterministic and has no timing dependence, so it cannot flake. ## Verification - `EventuallyTest` suite passes, including on `--rerun-tasks`. - The fix is count-based with no wall-clock component, so the result is invariant to runner load. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
align compile toolchain with minimum supported Kotlin version for KLI… …B ABI compatibility (#6134) Kotest's KMP/Native KLIBs were being compiled with the Kotlin 2.3.20 compiler, stamping KLIB ABI version 2.3.x into the artifacts. Consumers on Kotlin 2.2 would see the resolver skip these KLIBs with: ``` w: KLIB resolver: Skipping '...' having incompatible ABI version '2.3.0'. The library was produced by '2.3.20' compiler. ``` KLIB ABI compatibility is one-directional: newer compilers can consume older ABI versions, but not vice versa. To support users on any Kotlin version from 2.2 onwards, KLIBs must be produced by a 2.2 compiler. This project already uses the Gradle plugin / compiler version split (kotlin-gradle-plugin stays at 2.3.20 via compilerVersion in kotlin-conventions). This PR takes advantage of that: drop kotlin-compile-version and kotlin-core-libraries-version to 2.2.0 while leaving the Gradle plugin unchanged. Tooling and IDE support stay on 2.3.20; only the compiler binary and stdlib version used to produce artifacts changes. Note: kotlin-language-version was already set to 2.2.0 and wired up via languageVersion/apiVersion in `kotlin-conventions.gradle.kts`, so the source-level guardrail was already in place.
PreviousNext