Skip to content

Commit

Permalink
MicronautKotest5Extension now cleans up contexts after test spec is d…
Browse files Browse the repository at this point in the history
…one (#868)
  • Loading branch information
Spikhalskiy authored Oct 20, 2023
1 parent 666214c commit 2b3c5ef
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object MicronautKotest5Extension : TestListener, ConstructorExtension, TestCaseE

override suspend fun intercept(
testCase: TestCase,
execute: suspend (TestCase) -> TestResult
execute: suspend (TestCase) -> TestResult,
): TestResult {
val context = testCase.spec.context()
return if (context != null && context.getSpecDefinition() == null) {
Expand All @@ -42,18 +42,32 @@ object MicronautKotest5Extension : TestListener, ConstructorExtension, TestCaseE
execute(testCase)
}
}
val contexts: MutableMap<String, List<MicronautKotest5Context>> = mutableMapOf()

val contexts: MutableMap<String, MutableList<MicronautKotest5Context>> = mutableMapOf()

private fun Spec.context() =
contexts[javaClass.name]?.find { it.bean == this } ?: contexts[javaClass.name]?.find { it.bean == null }

/**
* Removes the context from the [contexts] map
*/
private fun MicronautKotest5Context.cleanupContext() {
val specClassName: String? = this.bean?.javaClass?.name
contexts[specClassName]?.let {
it.remove(this)
if (it.isEmpty()) contexts.remove(specClassName)
}
}

override suspend fun beforeSpec(spec: Spec) {
spec.context()?.beforeSpecClass(spec)
}

override suspend fun afterSpec(spec: Spec) {
spec.context()?.afterSpecClass(spec)
spec.context()?.let {
it.afterSpecClass(spec)
it.cleanupContext()
}
}

override suspend fun beforeTest(testCase: TestCase) {
Expand Down Expand Up @@ -94,8 +108,7 @@ object MicronautKotest5Extension : TestListener, ConstructorExtension, TestCaseE
} else {
val createBean = constructor != null && constructor.parameters.isNotEmpty()
val context = MicronautKotest5Context(testClass, micronautTestValue, createBean)
val specContexts = contexts[testClass.name] ?: emptyList()
contexts[testClass.name] = specContexts + context
contexts.getOrPut(testClass.name, ::mutableListOf).add(context)
if (createBean) {
context.bean
} else {
Expand All @@ -116,7 +129,7 @@ object MicronautKotest5Extension : TestListener, ConstructorExtension, TestCaseE
micronautTest.contextBuilder.map { kClass -> kClass.java }.toTypedArray(),
micronautTest.transactionMode,
micronautTest.startApplication,
false
false,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,12 @@ class IsolationModeTest : FunSpec({
val a = MicronautKotest5Extension.instantiate(IsolatedTests::class).shouldNotBeNull()
val b = MicronautKotest5Extension.instantiate(IsolatedTests::class).shouldNotBeNull()
a.hashCode() shouldNotBe b.hashCode()
MicronautKotest5Extension.contexts[IsolatedTests::class.java.name]
.shouldNotBeNull()
.shouldHaveSize(2)
MicronautKotest5Extension.contexts[IsolatedTests::class.java.name]
.shouldNotBeNull()
.forAll { it.isApplicationContextOpen() }
val contexts = MicronautKotest5Extension.contexts[IsolatedTests::class.java.name].shouldNotBeNull().toList()
contexts.shouldHaveSize(2)
contexts.forAll { it.isApplicationContextOpen() }
MicronautKotest5Extension.afterSpec(a)
MicronautKotest5Extension.afterSpec(b)
MicronautKotest5Extension.contexts[IsolatedTests::class.java.name]
.shouldNotBeNull()
.forAll { !it.isApplicationContextOpen() }
contexts.forAll { !it.isApplicationContextOpen() }
}
})

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.micronaut.test.kotest5

import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.nulls.shouldBeNull
import io.kotest.matchers.nulls.shouldNotBeNull
import io.micronaut.test.extensions.kotest5.MicronautKotest5Extension
import io.micronaut.test.extensions.kotest5.annotation.MicronautTest

class NoContextsRetentionTest : FunSpec({
test("extension should not retain references to contexts after tests are finished") {
MicronautKotest5Extension.contexts[NoContextsRetentionTests::class.java.name].shouldBeNull()
val a = MicronautKotest5Extension.instantiate(NoContextsRetentionTests::class).shouldNotBeNull()
val b = MicronautKotest5Extension.instantiate(NoContextsRetentionTests::class).shouldNotBeNull()
MicronautKotest5Extension.contexts[NoContextsRetentionTests::class.java.name].shouldNotBeNull().shouldHaveSize(2)
MicronautKotest5Extension.afterSpec(a)
MicronautKotest5Extension.contexts[NoContextsRetentionTests::class.java.name].shouldNotBeNull().shouldHaveSize(1)
MicronautKotest5Extension.afterSpec(b)
MicronautKotest5Extension.contexts[NoContextsRetentionTests::class.java.name].shouldBeNull()
}
})

@MicronautTest
// need a parameter here so the extension instantiates the spec
private class NoContextsRetentionTests(private val mathService: MathService) : FunSpec() {
init {
test("test1") {}
}
}

0 comments on commit 2b3c5ef

Please sign in to comment.