JUnit 5中assertThrows未捕获异常的Kotlin测试问题排查
JUnit 5 assertThrows 无法捕获 UserException 的问题修复
核心问题分析
你的测试代码存在两个致命错误,导致异常提前抛出且未被assertThrows捕获:
- 错误mock被测类方法:你尝试mock
userService.fetchUserById(1)返回null,但userService是真实的被测实例,而非Mockito创建的mock对象,执行该语句会直接调用真实方法,在setup阶段就触发了UserException,根本没走到assertThrows逻辑。 - 未正确配置依赖mock:你期望触发异常的条件是
usernameService.getUserNameById返回null,但未对该依赖方法的行为进行mock,测试逻辑与预期触发条件不匹配。
修正后的测试代码
import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.mockito.Mockito import org.mockito.Mockito.`when` class UserServiceTest { private val usernameService: UsernameService = Mockito.mock(UsernameService::class.java) private val subscriptionService: SubscriptionService = Mockito.mock(SubscriptionService::class.java) private val userService = UserService(usernameService, subscriptionService) @Test fun `getUserNameById throws exception if username is null`() { // 正确配置依赖mock:触发异常的条件 `when`(usernameService.getUserNameById(1)).thenReturn(null) // 配置subscriptionService返回有效值,避免触发第二个异常 `when`(subscriptionService.getSubscriptionByUserId(1)).thenReturn(Subscription("email@email.com")) // 显式指定捕获的异常类型,确保JUnit 5正确识别 val userException = assertThrows<UserException> { userService.fetchUserById(1) } // 验证异常消息符合预期 assert(userException.message == "No username") // 验证依赖服务的方法被正确调用 Mockito.verify(usernameService).getUserNameById(1) Mockito.verify(subscriptionService).getSubscriptionByUserId(1) } }
关键修正点说明
- 移除无效mock语句:删除
Mockito.when(userService.fetchUserById(1)).thenReturn(null),避免在setup阶段提前触发异常。 - 配置依赖mock行为:通过
usernameService.getUserNameById(1)返回null,精准触发UserService中抛出"No username"异常的逻辑。 - 显式指定异常类型:
assertThrows<UserException>明确告诉JUnit 5要捕获的异常类型,避免类型推断歧义。 - 修正verify逻辑:验证依赖服务的方法调用情况,而非被测类(真实实例无法被Mockito verify)。
内容的提问来源于stack exchange,提问作者James Nickelby
相关产品推荐
相关产品推荐

