如何让kotlintest与Spring一起工作?

我试图使用kotlintest与spring(不是春季启动,只是标准的春季测试)。 我觉得这很难做到。 任何指针,我在做什么错? 我也是Kotlin的新手,所以我可能不会做正确的事情。

这是我迄今为止所尝试的:

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" } } } } } 

输出:

 java.lang.InstantiationException: MyTests at java.lang.Class.newInstance(Class.java:427) at io.kotlintest.KTestJUnitRunner.(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.() at java.lang.Class.getConstructor0(Class.java:3082) at java.lang.Class.newInstance(Class.java:412) ... 40 more 

另一个尝试:

 import io.kotlintest.matchers.shouldBe import io.kotlintest.specs.BehaviorSpec import org.junit.ClassRule import org.junit.Rule import org.springframework.beans.factory.annotation.Autowired 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() @Autowired 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" } } } } } 

输出:

 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.(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.(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) 

这工作,但它不使用kotlintest – 它只是使用标准的JUnit,这是不是我想要的:

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

kotlintest不支持JUnit 4规则。

因此,你试图做的事情根本不可能。

要使用JUnit 4的Spring测试支持,您必须使用SpringRunnerSpringClassRuleSpringMethodRule的组合(使用支持JUnit 4规则的JUnit 4 Runner实现)。

另一方面,你可以切换到JUnit 5并使用SpringExtension 。 很多人似乎发现优于使用kotlintest在Kotlin编写测试。