如何在try/catch场景下直接测试kotlin-logging的日志输出?
直接用MockK测试kotlin-logging的日志调用
完全可以直接测试logger的调用,不需要额外封装MyLogger,利用MockK的mock能力就能实现。以下是具体实现方案:
被测代码示例
假设你有一个包含try/catch逻辑的业务类,针对特定异常输出info日志,其他异常输出warn日志:
import io.github.oshai.kotlinlogging.KotlinLogging class BusinessService { private val logger = KotlinLogging.logger {} fun process(input: String) { try { when (input) { "custom" -> throw CustomException("触发自定义异常") "normal" -> throw IllegalArgumentException("触发普通异常") else -> Unit // 正常业务逻辑 } } catch (e: CustomException) { logger.info { "已处理自定义异常: ${e.message}" } } catch (e: Exception) { logger.warn { "未处理异常: ${e.message}" } } } } class CustomException(message: String) : Exception(message)
测试实现方案
方案1:通过Spyk替换类内部的Logger实例
这种方式针对类的私有logger字段进行替换,更聚焦于单个被测对象的日志行为:
import io.github.oshai.kotlinlogging.Logger import io.mockk.every import io.mockk.mockk import io.mockk.spyk import io.mockk.verify import org.junit.jupiter.api.Test class BusinessServiceTest { @Test fun `触发自定义异常时输出info日志`() { // 1. 创建mock的Logger实例 val mockLogger = mockk<Logger>(relaxed = true) // 2. 创建被测类的spyk对象,替换内部logger val service = spyk(BusinessService()) { every { logger } returns mockLogger } // 执行测试逻辑 service.process("custom") // 验证日志调用 verify(exactly = 1) { mockLogger.info(eq("已处理自定义异常: 触发自定义异常")) } // 确保warn日志未被调用 verify(exactly = 0) { mockLogger.warn(any<String>()) } } @Test fun `触发普通异常时输出warn日志`() { val mockLogger = mockk<Logger>(relaxed = true) val service = spyk(BusinessService()) { every { logger } returns mockLogger } service.process("normal") verify(exactly = 1) { mockLogger.warn(eq("未处理异常: 触发普通异常")) } verify(exactly = 0) { mockLogger.info(any<String>()) } } }
方案2:Mock静态的Logger获取方法
如果不想用spyk,也可以直接mockKotlinLogging.logger()静态方法,让它返回预设的mock Logger:
import io.github.oshai.kotlinlogging.KotlinLogging import io.github.oshai.kotlinlogging.Logger import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic import io.mockk.verify import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test class BusinessServiceStaticMockTest { @AfterEach fun cleanUp() { unmockkStatic(KotlinLogging::class) } @Test fun `自定义异常输出info日志`() { mockkStatic(KotlinLogging::class) val mockLogger = mockk<Logger>(relaxed = true) // 让所有logger()调用返回mock实例 every { KotlinLogging.logger(any()) } returns mockLogger val service = BusinessService() service.process("custom") verify { mockLogger.info(eq("已处理自定义异常: 触发自定义异常")) } } }
关键注意点
- 使用
relaxed = true创建mock Logger时,无需手动设置每个日志方法的默认行为,简化测试代码 - 可以用
eq()做精确消息匹配,也可以用contains()实现模糊匹配(比如mockLogger.info(contains("自定义异常"))) - 静态mock后记得在测试结束时清理,避免影响其他测试用例
内容的提问来源于stack exchange,提问作者jactor-rises
相关产品推荐
相关产品推荐

