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

使用Mockito对Repository做单元测试返回NullPointerException求助

问题排查与解决方案

核心错误原因

  • 测试对象混淆:你需要测试的是RemoteDiscoverRepository的真实逻辑,错误地对真实测试对象remote的方法进行打桩,Mockito无法拦截真实对象的方法调用,导致remote.trendingMovie()执行真实逻辑时触发空指针
  • 依赖未打桩:你注入的retrofitServices是Mock对象,但没有对它的discover()方法做打桩,默认返回null,后续调用null的trendingMovieOfTheDay()方法直接触发空指针
  • 冗余无效Mock:额外声明的discoverRepository是完全无用的Mock实例,你最终调用它的方法不会执行任何真实逻辑,完全脱离测试目标

修正方案

调整测试逻辑:测试真实RemoteDiscoverRepository实例的逻辑,仅Mock它的依赖RetrofitServices和下层的DiscoverDao,对依赖的方法做合理打桩即可。修正后的测试代码如下:

@RunWith(MockitoJUnitRunner::class)
class DiscoverRepositoryTest {
  @get:Rule
  var instantTaskExecutorRule = InstantTaskExecutorRule()

  @Mock
  private lateinit var retrofitServices: RetrofitServices

  // 新增Mock DiscoverDao实例
  @Mock
  private lateinit var discoverDao: DiscoverDao

  private lateinit var remote : RemoteDiscoverRepository

  private val dummy = DiscoverDummy.getDiscover()

  @Before
  fun setup(){
      remote = RemoteDiscoverRepository(retrofitServices)
  } 

  @Test
  fun trendingMovieTest() = runBlocking {
    // 打桩依赖的返回值:retrofitServices.discover()返回mock的discoverDao
    `when`(retrofitServices.discover()).thenReturn(discoverDao)
    // 打桩discoverDao的方法返回构造好的成功响应
    `when`(discoverDao.trendingMovieOfTheDay()).thenReturn(Response.success(dummy.data))

    // 调用真实测试对象的方法
    val trending = remote.trendingMovie()
    
    // 验证依赖方法被调用
    verify(retrofitServices).discover()
    verify(discoverDao).trendingMovieOfTheDay()

    // 结果校验
    assertNotNull(trending)
    assertEquals(dummy.data?.results?.size, trending.data?.results?.size)
  }
}

额外优化建议

  • 协程调度优化:你当前代码里写死了Dispatchers.IO,建议将Dispatcher作为构造参数注入,单元测试时可以传入TestDispatcher,避免测试时的协程调度异常
  • 依赖适配:如果你使用的Mockito版本对suspend方法打桩有兼容问题,可以引入org.mockito.kotlin:mockito-kotlin依赖,它的API对Kotlin语法适配性更好

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 04:09:02