打开在配置 class 中声明的 bean
Opening bean declared in Configuration class
最近我遇到了 Spring、Kotlin 和 Spock 的奇怪问题。我有非常简单的项目(spring-boot,spring-web)。我有一个 Controller
,其中很少 Bean
注入到这个 Controller
。一切正常。问题在测试中。我无法模拟这些 Bean
中的任何一个。 kotlin-spring
/kotlin-allopen
不会向 Configuration
class 中定义的 bean 添加 open
签名。另一方面,如果我将此声明更改为 @Component
一切正常。
这是我的 build.gradle.kts
插件列表
plugins {
id("idea")
id("groovy")
id("maven-publish")
id("org.springframework.cloud.contract") version "2.2.5.RELEASE"
id("org.springframework.boot") version "2.4.1"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
kotlin("jvm") version "1.4.21"
kotlin("plugin.spring") version "1.4.21"
kotlin("plugin.allopen") version "1.4.21"
}
这是错误信息:
Caused by: org.spockframework.mock.CannotCreateMockException: Cannot create mock for class *** because Java mocks cannot mock final classes. If the code under test is written in Groovy, use a Groovy mock.
我知道它说我可以使用 GroovyMock
但我想在测试中设计我的基础 class 并且我想使用 @TestConfiguration
class。所以为了模拟那些 classes 我想使用 DetachedMockFactory
.
有没有办法将 Spock 配置为能够模拟来自 Kotlin 的最终 classes?或者有没有办法告诉 kotlin-spring
/kotlin-allopen
打开 classes 在 Configuration
class?
中定义为 beans
编辑:
我无法帮你修复spock-mockable问题,也许你想向作者寻求帮助。最近我已经在那个项目中修复了一个 Maven 问题,但现在似乎有一个 ByteBuddy 问题,试图重新定义一个已经加载的 class,这在 JVM 中是不可能的。我相信维护者可以帮助你。
与此同时,就像我在之前的评论中建议的那样,为您切换到 Sarek solves the problem, though. I created a corresponding pull request。
目前它使用默认的完整 Sarek 代理。如果您将 sarek-unfinal
添加为依赖项而不是 sarek
,并且还要确保在 属性 dev.sarek.agent.type=unfinal
中设置系统 Gradle Spock 测试的配置,您可以使用较小的 unfinal 代理而不使用其余的 Sarek 功能。 作为一个 Gradle 菜鸟,我不知道如何配置它。
更新: 不再需要上面提到的附加系统属性。最新的 Sarek 快照在 class 路径上时自动检测未最终代理(或 4 种 Sarek 代理中的任何其他类型)。我知道您已决定使用 spock-mockable,但我想让这个答案保持最新以供参考。参见 this diff for what the pull request would look like now, especially this simple commit。
如果您目前在使用快照版本时遇到任何问题,请告诉我。如果这是一个商业项目,并且您需要构建一个在某些时候禁止使用快照版本的版本,我可以在 Maven Central 上发布 1.0 或 0.8 或其他任何版本。现在我只是将 Maven Central 快照存储库 (Sonatype OSS) 添加到您的构建中。
感谢大家的帮助! @kriegaex 您的解决方案非常有效,谢谢!
关于 spock-mockable
,我与该库的作者进行了交谈,他弄清楚了为什么 spock-mockable
无法使用我的设置 (GH issue)。这是因为 spock-spring
扩展名。根本原因是 spock-spring
扩展在 spock-mockable
之前加载。当 Spring/Spock 想从 @TestConfiguration
class 创建模拟时,它不能,因为 kotlin-spring
插件不会打开 classes 在 [=17] 中声明为 beans =] class 和 spock-mockable
此时未加载。笑话改变了他的扩展程序的加载方式,所以现在 spock-mockable
和 sarek
两个解决方案都有效。
我相信我的问题就此结束 ;)
最近我遇到了 Spring、Kotlin 和 Spock 的奇怪问题。我有非常简单的项目(spring-boot,spring-web)。我有一个 Controller
,其中很少 Bean
注入到这个 Controller
。一切正常。问题在测试中。我无法模拟这些 Bean
中的任何一个。 kotlin-spring
/kotlin-allopen
不会向 Configuration
class 中定义的 bean 添加 open
签名。另一方面,如果我将此声明更改为 @Component
一切正常。
这是我的 build.gradle.kts
插件列表
plugins {
id("idea")
id("groovy")
id("maven-publish")
id("org.springframework.cloud.contract") version "2.2.5.RELEASE"
id("org.springframework.boot") version "2.4.1"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
kotlin("jvm") version "1.4.21"
kotlin("plugin.spring") version "1.4.21"
kotlin("plugin.allopen") version "1.4.21"
}
这是错误信息:
Caused by: org.spockframework.mock.CannotCreateMockException: Cannot create mock for class *** because Java mocks cannot mock final classes. If the code under test is written in Groovy, use a Groovy mock.
我知道它说我可以使用 GroovyMock
但我想在测试中设计我的基础 class 并且我想使用 @TestConfiguration
class。所以为了模拟那些 classes 我想使用 DetachedMockFactory
.
有没有办法将 Spock 配置为能够模拟来自 Kotlin 的最终 classes?或者有没有办法告诉 kotlin-spring
/kotlin-allopen
打开 classes 在 Configuration
class?
编辑:
我无法帮你修复spock-mockable问题,也许你想向作者寻求帮助。最近我已经在那个项目中修复了一个 Maven 问题,但现在似乎有一个 ByteBuddy 问题,试图重新定义一个已经加载的 class,这在 JVM 中是不可能的。我相信维护者可以帮助你。
与此同时,就像我在之前的评论中建议的那样,为您切换到 Sarek solves the problem, though. I created a corresponding pull request。
目前它使用默认的完整 Sarek 代理。如果您将 sarek-unfinal
添加为依赖项而不是 sarek
,并且还要确保在 属性 中设置系统 Gradle Spock 测试的配置,您可以使用较小的 unfinal 代理而不使用其余的 Sarek 功能。 dev.sarek.agent.type=unfinal
作为一个 Gradle 菜鸟,我不知道如何配置它。
更新: 不再需要上面提到的附加系统属性。最新的 Sarek 快照在 class 路径上时自动检测未最终代理(或 4 种 Sarek 代理中的任何其他类型)。我知道您已决定使用 spock-mockable,但我想让这个答案保持最新以供参考。参见 this diff for what the pull request would look like now, especially this simple commit。
如果您目前在使用快照版本时遇到任何问题,请告诉我。如果这是一个商业项目,并且您需要构建一个在某些时候禁止使用快照版本的版本,我可以在 Maven Central 上发布 1.0 或 0.8 或其他任何版本。现在我只是将 Maven Central 快照存储库 (Sonatype OSS) 添加到您的构建中。
感谢大家的帮助! @kriegaex 您的解决方案非常有效,谢谢!
关于 spock-mockable
,我与该库的作者进行了交谈,他弄清楚了为什么 spock-mockable
无法使用我的设置 (GH issue)。这是因为 spock-spring
扩展名。根本原因是 spock-spring
扩展在 spock-mockable
之前加载。当 Spring/Spock 想从 @TestConfiguration
class 创建模拟时,它不能,因为 kotlin-spring
插件不会打开 classes 在 [=17] 中声明为 beans =] class 和 spock-mockable
此时未加载。笑话改变了他的扩展程序的加载方式,所以现在 spock-mockable
和 sarek
两个解决方案都有效。
我相信我的问题就此结束 ;)