You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring非Boot项目中使用Mockk模拟Bean失败,求解决方案

问题:非Spring Boot项目中用MockK模拟Bean进行控制器测试失败

在非Spring Boot项目中尝试使用mockk()模拟Bean完成控制器测试时失败。PostController依赖PostRepository Bean,我已在测试配置中通过mockk()模拟该Bean,但测试未按预期运行。测试代码如下:

@SpringJUnitConfig(classes = [PostControllerTest.TestConfig::class])
class PostControllerTest {
    companion object {
        private val log = LoggerFactory.getLogger(PostControllerTest::class.java)
    }

    @Configuration(proxyBeanMethods = false)
    @ComponentScan(basePackageClasses = [PostController::class])
    internal class TestConfig {

        @Bean
        @Primary
        fun postRepository(): PostRepository = mockk<PostRepository>()
    }

    @Autowired
    lateinit var posts: PostRepository

    lateinit var client: WebTestClient

    @BeforeEach
    fun setup() {
        log.debug("calling setup...")
        client = WebTestClient.bindToController(PostController::class)
            .configureClient()
            .build()
    }

    @AfterEach
    fun teardown() {
        clearAllMocks()
    }

    @Test
    fun `get post by id`() = runTest {
        val id = UUID.randomUUID().toString()
        coEvery { posts.findById(any()) } returns
                Post(
                    id = id,
                    title = "test title",
                    content = "content of test title"
                )
        client.get().uri("/posts/$id")
            .exchange()
            .expectStatus().isOk
            .expectBody().jsonPath("$.title").isEqualTo("test title")

        coVerify(exactly = 1) { posts.findById(any()) }
    }

}

项目环境:

  • Spring 6.1.x WebFlux
  • Kotlin 1.9.22 + Kotlin Coroutines 1.7.3
  • Java 21

此前在Java代码中使用Mockito以相同方式模拟Bean是可行的。


解决方案

核心问题在于WebTestClient.bindToController(PostController::class)的用法:该方法会直接实例化PostController,不会从Spring容器中获取已注入MockK模拟Bean的控制器实例,导致控制器内的PostRepository并非你配置的MockK实例。

调整测试代码,改为从Spring容器注入PostController实例来构建WebTestClient:

@SpringJUnitConfig(classes = [PostControllerTest.TestConfig::class])
class PostControllerTest {
    // ... 其他代码保持不变

    @Autowired
    lateinit var postController: PostController

    @BeforeEach
    fun setup() {
        log.debug("calling setup...")
        client = WebTestClient.bindToController(postController)
            .configureClient()
            .build()
    }

    // ... 其他代码保持不变
}

同时需确保PostController通过Spring依赖注入方式获取PostRepository(比如构造函数注入或@Autowired注解),这样容器中的控制器实例才会使用你配置的MockK版本PostRepository。

补充说明:

  • bindToController(Class)方法绕过Spring依赖注入直接创建控制器对象,因此容器中的MockK Bean无法被注入。
  • 使用容器注入的控制器实例后,Spring会自动将MockK模拟的PostRepository注入到控制器中,此时测试中的coEvery和coVerify才能正确作用在MockK实例上。

内容的提问来源于stack exchange,提问作者Hantsy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:08:11