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

Java中Mock静态方法未生效:如何正确Mock CacheSystemToCacheManagerProvider?

如何正确Mock静态方法解决单元测试依赖问题

我在编写MyMainClass的单元测试时,尝试用Mockito的mockStatic来MockCacheSystemToCacheManagerProvider类的getCacheBuilder静态方法,但Mock没生效,实际触发了真实调用,创建了CommonCaffeineCacheBuilder实例,引入大量依赖导致单元测试失败。相关代码如下:

MyMainClass类

public class MyMainClass{
    
    public void mainLogic(){
        handleEvictedKeys(key, value, removalCause);
    }

    private void handleEvictedKeys(final Object key, final Object value, final RemovalCause removalCause) {
        if (removalCause.equals(RemovalCause.SIZE)) {
            remote.setOrReplaceValueForKey((String) key, (Map<String, String>) value);
        } else {
            log.warn("Key {} and Value {} was evicted from cache for theme {} for the reason {}", key, value,
                cacheInformation.getThemeName(), removalCause);
        }
    }

    private RemoteCacheManager buildRemoteCacheManager() {
        GenericCacheBuilder genericCacheBuilder = CacheSystemToCacheManagerProvider
            .getCacheBuilder(cacheInformation.getRemoteCachePreference());
        return (RemoteCacheManager) genericCacheBuilder.buildCacheManager(cacheInformation);
    }
}

CacheSystemToCacheManagerProvider类

public class CacheSystemToCacheManagerProvider {

    private static final ImmutableMap<AllowedCacheSystem, GenericCacheBuilder<?>> CACHE_SYSTEM_TO_CACHE_BUILDER_MAP =
        ImmutableMap.<AllowedCacheSystem, GenericCacheBuilder<?>>builder()
            .put(AllowedLocalCacheSystem.COMMON_CAFFEINE, new CommonCaffeineCacheBuilder())
            .put(AllowedRemoteCacheSystem.COMMON_REDIS, new CommonRedisCacheBuilder())
            .build();
    
    
    public static GenericCacheBuilder getCacheBuilder(AllowedCacheSystem cacheSystem) {
        return CACHE_SYSTEM_TO_CACHE_BUILDER_MAP.get(cacheSystem);
    }
}

原测试类代码

public class TestMyMainClass {

    @InjectMocks
    public MyMainClass mtestClass;

    public void mymainLogic(){
        MockedStatic<CacheSystemToCacheManagerProvider> cacheSystemToCacheManagerProviderStatic = Mockito.mockStatic(CacheSystemToCacheManagerProvider.class);
        cacheSystemToCacheManagerProviderStatic.when(
                CacheSystemToCacheManagerProvider::getCacheBuilder)
            .thenReturn(getCacheBuilderMock);
        mtestClass.handleEvictedKeys(a,b,c);
    }
}

问题原因

你的Mock写法存在两个核心问题:

  • 没有指定getCacheBuilder方法的参数匹配逻辑,Mockito无法匹配真实调用时传入的具体AllowedCacheSystem参数,因此会执行真实方法。
  • 测试中调用的handleEvictedKeys方法根本没有触发getCacheBuilder的调用,Mock自然不会生效。

正确解决步骤

1. 用参数匹配器明确Mock规则

必须为静态方法的入参指定匹配逻辑,比如用any()匹配任意参数,或者指定具体枚举值:

// 用try-with-resources包裹,确保Mock自动销毁,避免影响其他测试
try (MockedStatic<CacheSystemToCacheManagerProvider> mockedStatic = Mockito.mockStatic(CacheSystemToCacheManagerProvider.class)) {
    // 匹配任意AllowedCacheSystem类型的参数
    mockedStatic.when(() -> CacheSystemToCacheManagerProvider.getCacheBuilder(Mockito.any(AllowedCacheSystem.class)))
               .thenReturn(getCacheBuilderMock);
    
    // 执行会触发静态方法的业务逻辑
    mtestClass.mainLogic();
}

2. 确保测试逻辑触发目标静态方法

原测试中调用的handleEvictedKeys不会调用getCacheBuilder,需要调用mainLogic或者直接调用buildRemoteCacheManager方法,确保静态方法被触发。

3. 补充后续方法的Mock(必要)

为了避免buildCacheManager调用出错,需要提前Mock这个方法的返回值:

// 先Mock RemoteCacheManager实例
RemoteCacheManager mockRemoteCacheManager = Mockito.mock(RemoteCacheManager.class);
// 配置getCacheBuilderMock的buildCacheManager方法返回mock实例
Mockito.when(getCacheBuilderMock.buildCacheManager(Mockito.any(CacheInformation.class)))
       .thenReturn(mockRemoteCacheManager);

4. 验证Mock是否生效(可选)

可以添加验证代码,确认静态方法确实被调用:

mockedStatic.verify(() -> CacheSystemToCacheManagerProvider.getCacheBuilder(Mockito.any(AllowedCacheSystem.class)), Mockito.times(1));

完整测试类示例

public class TestMyMainClass {

    @InjectMocks
    private MyMainClass mtestClass;

    // 提前准备好GenericCacheBuilder的Mock实例
    private GenericCacheBuilder getCacheBuilderMock = Mockito.mock(GenericCacheBuilder.class);

    @Test
    public void testMainLogic() {
        // 静态类Mock,自动关闭
        try (MockedStatic<CacheSystemToCacheManagerProvider> mockedStatic = Mockito.mockStatic(CacheSystemToCacheManagerProvider.class)) {
            // 配置静态方法Mock行为
            mockedStatic.when(() -> CacheSystemToCacheManagerProvider.getCacheBuilder(Mockito.any(AllowedCacheSystem.class)))
                       .thenReturn(getCacheBuilderMock);
            
            // Mock buildCacheManager的返回值
            RemoteCacheManager mockRemoteCacheManager = Mockito.mock(RemoteCacheManager.class);
            Mockito.when(getCacheBuilderMock.buildCacheManager(Mockito.any(CacheInformation.class)))
                   .thenReturn(mockRemoteCacheManager);
            
            // 执行触发静态方法的业务逻辑
            mtestClass.mainLogic();
            
            // 验证静态方法调用次数
            mockedStatic.verify(() -> CacheSystemToCacheManagerProvider.getCacheBuilder(Mockito.any(AllowedCacheSystem.class)), Mockito.times(1));
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:02:54