使用 WebTestClient.bindToRouterFunction() 进行测试不适用于 kotlin - 无法从最终类继承

问题描述

我有以下测试

class MyTest{
    private val s1= mockk<S1>()
    private val s2= mockk<S2>()
    private val s3= mockk<S3>()

    private val requestHandler = RequestHandler(s1,s2,s3)

    private val webTestClient = WebTestClient
        .bindToRouterFunction(RouterConfiguration(requestHandler).router())
        .build();

    @Test
    fun test1() {
        ...

        val result = webTestClient.post()
            ...
            .returnResult()

        assertNull(result.responseBody)
    }
}

和路由器配置

@Configuration
class RouterConfiguration(
    private val handler: RequestHandler,) {
    fun router() = coRouter {
        "/api/v1".nest {
            ...
        }
    }
}

当我尝试运行测试时出现以下错误

Cannot inherit from final class
java.lang.VerifyError: Cannot inherit from final class
    at java.base/java.lang.classLoader.defineClass1(Native Method)
    at java.base/java.lang.classLoader.defineClass(ClassLoader.java:1017)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151)
    at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:821)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClasspathOrNull(BuiltinClassLoader.java:719)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:642)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:600)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.classLoader.loadClass(ClassLoader.java:522)
    at org.springframework.http.codec.support.BaseDefaultCodecs.getKotlinSerializationjsonDecoder(BaseDefaultCodecs.java:561)
    at org.springframework.http.codec.support.BaseDefaultCodecs.getobjectReaders(BaseDefaultCodecs.java:394)
    at org.springframework.http.codec.support.BaseCodecConfigurer.getReaders(BaseCodecConfigurer.java:100)
    at org.springframework.http.codec.support.DefaultServerCodecConfigurer.getReaders(DefaultServerCodecConfigurer.java:27)
    at org.springframework.web.reactive.function.server.DefaultHandlerStrategiesBuilder.build(DefaultHandlerStrategiesBuilder.java:101)
    at org.springframework.web.reactive.function.server.HandlerStrategies.withDefaults(HandlerStrategies.java:89)
    at org.springframework.test.web.reactive.server.DefaultRouterFunctionSpec.<init>(DefaultRouterFunctionSpec.java:36)
    at org.springframework.test.web.reactive.server.WebTestClient.bindToRouterFunction(WebTestClient.java:200)
    at mypgk.<init>(MyTest.kt:28)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

我无法弄清楚问题是什么,到目前为止我还没有找到答案。

Spring 文档配置:https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html#webtestclient-fn-config

版本

kotlin("jvm") version "1.4.21"
kotlin("plugin.spring") version "1.4.21"
kotlin("plugin.serialization") version "1.4.21"
id("org.springframework.boot") version "2.4.1"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
testImplementation("io.mockk:mockk:1.10.4")
testImplementation("io.projectreactor:reactor-test:3.4.2")

解决方法

在 Kotlin 中,默认情况下所有类都隐式标记为 final。如果要从类继承,则必须在类声明前显式添加 open 关键字。

@Configuration
open class RouterConfiguration(
    private val handler: RequestHandler,) {
    fun router() = coRouter {
        "/api/v1".nest {
            ...
        }
    }
}