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

使用Mockk的单元测试CI失败但本地正常的问题求助

问题分析

你遇到的核心矛盾是:本地Mock的GetForecastUseCase能正常拦截方法调用,但Bitrise Ubuntu 22.04环境下却触发了真实类的execute方法,导致repository空指针异常。这说明CI环境中Mockk没有正确生成代理类,真实的GetForecastUseCase实例被创建(而该实例的repository因未注入依赖为空)。

解决建议

1. 修正Mockk对Final类的Mock能力

Kotlin默认类和方法都是final的,Mockk需要特殊处理才能Mock final类。本地环境可能因IDE或JDK配置自动兼容,但CI环境可能缺失相关配置:

  • 方案A:给用例类添加open修饰符
    修改GetForecastUseCase类,让它可以被Mockk代理:
    open class GetForecastUseCase @Inject constructor(
        private val repository: WeatherForecastRepository
    ) {
        open fun execute(
            lat: String,
            long: String
        ): Flow<Forecast> = repository.getLocationForecast(lat, long)
    }
    
  • 方案B:使用All-Open插件批量处理
    在项目根目录的build.gradle中配置All-Open插件,让测试相关类自动变为非final:
    plugins {
        id 'org.jetbrains.kotlin.plugin.allopen' version '你的Kotlin版本'
    }
    
    allOpen {
        annotation 'org.junit.jupiter.api.TestInstance'
        // 或直接指定测试类所在包
        // packages 'com.sevban.feature_home.test'
    }
    

2. 确保Mockk Agent在CI环境中生效

Mockk Agent是处理final类Mock的核心组件,需确认CI环境已正确引入并启用:

  • 在模块build.gradle中添加Agent依赖:
    testImplementation "io.mockk:mockk:1.13.8" // 替换为你的Mockk版本
    testImplementation "io.mockk:mockk-agent-jvm:1.13.8"
    
  • 强制CI测试任务启用Agent,在模块build.gradle中添加:
    tasks.withType(Test) {
        jvmArgs "-javaagent:${classpath.find { it.name.contains('mockk-agent') }.absolutePath}"
    }
    

3. 避免依赖relaxed = true,显式Mock方法

relaxed = true虽然便捷,但对final类的Mock稳定性较差,建议显式定义所有需要拦截的方法行为:
修改setUp方法,提前Mockexecute的默认行为:

@BeforeEach
fun setUp() {
    getForecastUseCase = mockk() // 去掉relaxed=true
    // 提前定义默认行为,避免测试方法中延迟设置导致真实调用
    every { getForecastUseCase.execute(any(), any()) } returns flowOf(dummyForecast)
    savedStateHandle = SavedStateHandle()
    viewModel = DetailViewModel(getForecastUseCase, savedStateHandle)
}

4. 对齐本地与CI的环境配置

  • 检查CI使用的JDK版本,确保与本地一致(比如本地用Azul Zulu 17,CI也配置相同版本)。
  • 确认CI的Gradle构建命令与本地一致,比如是否使用testDebugUnitTest而非其他变体,避免依赖差异。

5. 排查CI缓存问题

Bitrise的缓存可能残留旧编译产物,尝试:

  • 在CI流程中添加./gradlew clean步骤后再运行测试。
  • 临时禁用Bitrise的Gradle缓存,确认是否是缓存导致的问题。

内容的提问来源于stack exchange,提问作者Sevban Bayır

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:53:16