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

如何用Mockito-inline模拟父类并阻止调用其真实构造方法?

问题背景与解决方案

核心问题

使用JUnit 4 + Mockito 5.2(依赖mockito-inline的内联MockMaker)移除PowerMockito依赖时,遇到Android类LruCache的构造方法在非Android环境下抛出Stub异常的问题:项目中BitmapCache extends LruCache<Uri, Bitmap>,子类构造方法调用super(cache_size)触发异常,需要模拟LruCache以避免调用真实构造,但mockConstruction无法拦截子类的super()调用。

关键原因

Mockito的mockConstruction仅能拦截直接实例化目标类的场景(如new LruCache(...)),子类构造中的super()属于类内部的父类构造调用,不会被拦截,因此仍会触发真实LruCache构造的异常。

可行解决方案

方案:直接模拟BitmapCache并覆盖父类方法行为

不需要单独模拟LruCache,直接通过mockConstruction创建BitmapCache的mock对象,既避免调用真实构造(包括父类super()),又能测试子类自身的业务逻辑,同时覆盖父类方法的行为:

@Test
public void testBitmapCache() {
    Bitmap bitmap1 = mock(Bitmap.class);
    Bitmap bitmap2 = mock(Bitmap.class);
    Uri uri1 = mock(Uri.class);
    Uri uri2 = mock(Uri.class);
    BitmapLoader loader = mock(BitmapLoader.class);
    int cacheSize = 1024;

    try (MockedConstruction<BitmapCache> mockedCache = mockConstruction(BitmapCache.class, (mock, context) -> {
        // 让BitmapCache的get/put调用真实方法,测试子类自身逻辑
        when(mock.put(any(Uri.class), any(Bitmap.class))).thenCallRealMethod();
        when(mock.get(any(Uri.class))).thenCallRealMethod();

        // 覆盖父类LruCache的方法行为,避免触发真实逻辑
        when(mock.get(uri1)).thenReturn(bitmap1);
        when(mock.get(uri2)).thenReturn(bitmap2);
        when(mock.get(any(Uri.class))).thenReturn(null);
        doNothing().when(mock).put(any(Uri.class), any(Bitmap.class));
    })) {
        // 创建mock实例,不会调用真实构造(包括super())
        BitmapCache cache = new BitmapCache(cacheSize, loader);

        // 执行测试逻辑
        cache.put(uri1, bitmap1);
        cache.put(uri2, bitmap2);

        assertEquals(bitmap1, cache.get(uri1));
        assertEquals(bitmap2, cache.get(uri2));
    }
}

方案说明

  1. 避免真实构造调用:mockConstruction(BitmapCache.class)创建的mock对象不会执行真实的构造方法(包括父类super()),彻底规避Stub异常。
  2. 保留子类逻辑测试:通过thenCallRealMethod()让BitmapCache的get/put调用真实方法,确保测试子类自身的业务逻辑。
  3. 覆盖父类方法:直接给mock对象的父类方法设置预期行为,当子类真实方法调用super.get()/super.put()时,会触发mock逻辑而非真实LruCache的方法。

为什么之前的尝试无效?

  1. 模拟LruCache无法拦截子类super()调用:mockConstruction不处理类内部的父类构造调用,因此仍会触发真实LruCache构造。
  2. 同时模拟两个类导致冲突:BitmapCache的mock已包含父类LruCache的mock行为,单独模拟LruCache不会影响子类mock的父类方法调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 20:35:14