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
相关产品推荐
相关产品推荐

