如何为Kotlin中带.also调用的duplicate方法编写单元测试?
问题:单元测试无法覆盖Kotlin方法中
.also块的逻辑 我为服务类的duplicate方法编写了单元测试,该方法末尾带有.also调用,但测试未覆盖这部分逻辑,运行时verify断言不通过。
服务类duplicate方法代码
suspend fun duplicate(id: ObjectId): Foo { val foo = findById(id) reset(foo) return create(foo).also { externalClient.doSomething(foo) } }
现有单元测试代码
@Test fun `should duplicate`() = runTest { wheneverBlocking { fooRepository.findById(any()) } doReturn Foo().apply { ... } wheneverBlocking { fooRepository.save(any()) } doAnswer { it.getArgument(0) } val res = fooService.duplicate(ObjectId()) verify(externalclient, times(1)).doSomething(any()) }
解决方案
1. 修正变量名拼写错误
测试中externalclient的拼写与方法里的externalClient大小写不一致(方法里是大写C,测试里是小写c),这会导致verify无法定位到正确的Mock实例,直接引发断言失败。
2. 确保Mock实例正确注入
确认fooService依赖的externalClient是测试中创建的Mock对象,而非新生成的真实实例。若依赖注入错误,verify会调用未被Mock的真实对象,自然无法通过断言。
3. 可选:精确匹配参数(提升测试严谨性)
如果需要更严格的验证,可以用测试预定义的foo对象替代any(),确保doSomething调用的参数符合预期:
@Test fun `should duplicate`() = runTest { // 预定义测试用的Foo对象 val testFoo = Foo().apply { // 初始化必要属性 } wheneverBlocking { fooRepository.findById(any()) } doReturn testFoo wheneverBlocking { fooRepository.save(any()) } doAnswer { it.getArgument(0) } fooService.duplicate(ObjectId()) // 用预定义的testFoo匹配参数,替代any() verify(externalClient, times(1)).doSomething(testFoo) }
补充说明
.also块的执行时机是create(foo)返回后、方法返回结果之前,并非方法返回后才执行。只要方法正常执行完毕,.also内的逻辑一定会被触发,测试失败的核心原因还是Mock实例的引用问题或拼写错误。
内容的提问来源于stack exchange,提问作者Alice
相关产品推荐
相关产品推荐

