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
相关产品推荐
相关产品推荐

