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

Android Kotlin用MockK Mock FirebaseAuth.getInstance()遇异常的解决方法

问题

在使用Kotlin和MockK为Android项目的ProfileScreenViewModel编写单元测试时,遇到MockKException: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock异常。

ViewModel中通过静态方法初始化user属性:

// Inside ProfileScreenViewModel
private val user = FirebaseAuth.getInstance().currentUser

测试初始化代码如下:

// Inside ProfileScreenViewModelTest
@Before
fun setUp() {
    // Mock FirebaseAuth
    val mockFirebaseAuth = mockk<FirebaseAuth>()
    val mockFirebaseUser = mockk<FirebaseUser>()
    every { mockFirebaseAuth.currentUser } returns mockFirebaseUser
    every { FirebaseAuth.getInstance() } returns mockFirebaseAuth
    
    // Mock other dependencies
    mockRepository = mockk()
    mockTimeProvider = mockk()
    
    // Initialize ViewModel with mocks
    viewModel = ProfileScreenViewModel(mockRepository, mockTimeProvider)
}

期望FirebaseAuth.getInstance().currentUser返回模拟的FirebaseUser,但在every { FirebaseAuth.getInstance() } returns mockFirebaseAuth行抛出异常。尝试仅模拟currentUser时,ViewModel的user属性为null,且不想通过构造函数传入user。

解决方案

问题核心在于FirebaseAuth.getInstance()是静态方法,MockK默认仅支持模拟实例对象,要拦截静态方法调用,需使用mockkStatic工具处理:

  1. 在测试初始化方法中,先模拟FirebaseAuth类的静态行为:
@Before
fun setUp() {
    // 第一步:模拟FirebaseAuth的静态方法
    mockkStatic(FirebaseAuth::class)
    
    val mockFirebaseAuth = mockk<FirebaseAuth>()
    val mockFirebaseUser = mockk<FirebaseUser>()
    
    // 第二步:配置静态方法返回模拟的FirebaseAuth实例
    every { FirebaseAuth.getInstance() } returns mockFirebaseAuth
    // 第三步:配置模拟实例的currentUser返回预设的模拟用户
    every { mockFirebaseAuth.currentUser } returns mockFirebaseUser
    
    // Mock其他依赖
    mockRepository = mockk()
    mockTimeProvider = mockk()
    
    // 初始化ViewModel
    viewModel = ProfileScreenViewModel(mockRepository, mockTimeProvider)
}
  1. (可选)为避免静态模拟污染其他测试,在测试结束后清理静态模拟:
@After
fun tearDown() {
    unmockkStatic(FirebaseAuth::class)
}

关键注意事项:

  • 必须先调用mockkStatic(FirebaseAuth::class),才能对FirebaseAuth.getInstance()这类静态方法使用every { ... }配置返回逻辑
  • 静态模拟是全局生效的,测试完成后执行unmockkStatic可以保证测试用例之间的独立性

内容的提问来源于stack exchange,提问作者Thimphou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:42:41