Hi,
I haev recently discovered that JUnit 5 allow you to control whether or not it reuses an instance of a test class for all tests, or creates a new instance for each test. However, the org.osgi:org.osgi.test.junit5
extension artifact doesn’t appear to support @TestInstance
.
This test class works:
package com.example.stuff.testing
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.osgi.framework.Bundle
import org.osgi.framework.BundleContext
import org.osgi.service.component.annotations.RequireServiceComponentRuntime
import org.osgi.test.common.annotation.InjectBundleContext
import org.osgi.test.junit5.context.BundleContextExtension
@ExtendWith(value = [ BundleContextExtension::class ])
@RequireServiceComponentRuntime
class WorkingTest {
companion object {
@InjectBundleContext
lateinit var bundleContext: BundleContext
private lateinit var testBundle: Bundle
@Suppress("unused")
@BeforeAll
@JvmStatic
fun setup() {
testBundle = bundleContext.bundle
}
}
@Test
fun myTest() {
assertEquals("testing", testBundle.symbolicName)
}
}
whereas this one does not:
package com.example.stuff.testing
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
import org.junit.jupiter.api.extension.ExtendWith
import org.osgi.framework.Bundle
import org.osgi.framework.BundleContext
import org.osgi.service.component.annotations.RequireServiceComponentRuntime
import org.osgi.test.common.annotation.InjectBundleContext
import org.osgi.test.junit5.context.BundleContextExtension
@ExtendWith(value = [ BundleContextExtension::class ])
@RequireServiceComponentRuntime
@TestInstance(PER_CLASS)
class NotWorkingTest {
@InjectBundleContext
lateinit var bundleContext: BundleContext
private lateinit var testBundle: Bundle
@BeforeAll
fun setup() {
testBundle = bundleContext.bundle
}
@Test
fun myTest() {
assertEquals("testing", testBundle.symbolicName)
}
}
The exception in the error case is:
# Execution Finished: NotWorkingTest - [engine:bnd-bundle-engine]/[bundle:testing;1.0.0.SNAPSHOT]/[sub-engine:junit-jupiter]/[class:com.example.stuff.testing.NotWorkingTest] - TestExecutionResult [status = FAILED, throwable = kotlin.UninitializedPropertyAccessException: lateinit property bundleContext has not been initialized]
kotlin.UninitializedPropertyAccessException: lateinit property bundleContext has not been initialized
at com.example.stuff.testing.NotWorkingTest.setup(NotWorkingTest.kt:26)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
...
which suggests that the injection would have happened in the @BeforeEach
phase rather than the @BeforeAll
phase.
@InjectService
gives similar results.
The point of @TestInstance
is that @BeforeAll
/@AfterAll
-scoped items no longer need to be static
, and I suspect org.osgi.test.junit5
is not handling this case.
Cheers,
Chris