¿Cómo hacer que kotlintest trabaje con Spring?

Intento usar kotlintest junto con Spring (no Spring Boot, solo la spring estándar). Me resulta muy difícil de hacer. ¿Alguna sugerencia sobre lo que estoy haciendo mal? También soy un novato de Kotlin así que no podría estar haciendo algo correctamente.

Esto es lo que he intentado hasta ahora:

import io.kotlintest.matchers.shouldBe import io.kotlintest.specs.BehaviorSpec import org.junit.ClassRule import org.junit.Rule import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.junit4.rules.SpringClassRule import org.springframework.test.context.junit4.rules.SpringMethodRule open class SomeBean { open fun sayHello() = "Hello" } @Configuration open class TestConfig { @Bean open fun someBean(): SomeBean = SomeBean() } @ContextConfiguration(classes = arrayOf(TestConfig::class)) open class MyTests(var someBean: SomeBean) : BehaviorSpec() { @Rule @JvmField val springMethodRule: SpringMethodRule = SpringMethodRule() companion object { @ClassRule @JvmField val SPRING_CLASS_RULE: SpringClassRule = SpringClassRule() } init { given("A test") { `when`("When my test happens") { val hello = someBean.sayHello() then("Hello should be valid") { hello shouldBe "Hello" } } } } } 

Salida:

 java.lang.InstantiationException: MyTests at java.lang.Class.newInstance(Class.java:427) at io.kotlintest.KTestJUnitRunner.<init>(KTestJUnitRunner.kt:13) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104) at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86) at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59) at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26) at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59) at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) at com.sun.proxy.$Proxy1.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128) at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NoSuchMethodException: MyTests.<init>() at java.lang.Class.getConstructor0(Class.java:3082) at java.lang.Class.newInstance(Class.java:412) ... 40 more 

Otro bash:

 import io.kotlintest.matchers.shouldBe import io.kotlintest.specs.BehaviorSpec import org.junit.ClassRule import org.junit.Rule import org.springframework.beans.factory.annotation.Autowinetworking import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.junit4.rules.SpringClassRule import org.springframework.test.context.junit4.rules.SpringMethodRule open class SomeBean { open fun sayHello() = "Hello" } @Configuration open class TestConfig { @Bean open fun someBean(): SomeBean = SomeBean() } @ContextConfiguration(classes = arrayOf(TestConfig::class)) open class MyTests : BehaviorSpec() { @Rule @JvmField val springMethodRule: SpringMethodRule = SpringMethodRule() @Autowinetworking lateinit var someBean: SomeBean companion object { @ClassRule @JvmField val SPRING_CLASS_RULE: SpringClassRule = SpringClassRule() } init { given("A test") { `when`("When my test happens") { val hello = someBean.sayHello() then("Hello should be valid") { hello shouldBe "Hello" } } } } } 

Salida:

 kotlin.UninitializedPropertyAccessException: lateinit property someBean has not been initialized at MyTests.getSomeBean(SpringTests.kt:31) at MyTests$1$1.invoke(SpringTests.kt:42) at MyTests$1$1.invoke(SpringTests.kt:25) at io.kotlintest.specs.BehaviorSpec$Given.when(BehaviorSpec.kt:27) at MyTests$1.invoke(SpringTests.kt:41) at MyTests$1.invoke(SpringTests.kt:25) at io.kotlintest.specs.BehaviorSpec.given(BehaviorSpec.kt:18) at MyTests.<init>(SpringTests.kt:40) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at java.lang.Class.newInstance(Class.java:442) at io.kotlintest.KTestJUnitRunner.<init>(KTestJUnitRunner.kt:13) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104) at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86) at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59) at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26) at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59) at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) at com.sun.proxy.$Proxy1.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128) at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) at java.lang.Thread.run(Thread.java:748) 

Esto funciona, pero no está usando kotlintest, solo está usando JUnit estándar, que no es lo que quiero:

 @ContextConfiguration(classes = arrayOf(TestConfig::class)) class Tests { @Rule @JvmField val springMethodRule: SpringMethodRule = SpringMethodRule() @Autowinetworking private lateinit var someBean: SomeBean companion object { @ClassRule @JvmField val SPRING_CLASS_RULE: SpringClassRule = SpringClassRule() } @Test fun runTest(): Unit { someBean.sayHello() shouldBe "Hello" } } 

    kotlintest no es compatible con las reglas JUnit 4.

    Por lo tanto, lo que estás tratando de hacer simplemente no es posible.

    Para usar el soporte de testing de Spring con JUnit 4, debe usar SpringRunner o la combinación de SpringMethodRule y SpringMethodRule (con una implementación de JUnit 4 Runner que admita las reglas de JUnit 4).

    Por otro lado, puede cambiar a JUnit 5 y usar SpringExtension . Mucha gente parece encontrar que es superior al uso de kotlintest para escribir testings en Kotlin.