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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 21:50:15