使用Mockito测试时无法注入Map,测试结果不符合预期怎么办?
测试失败原因及解决方案
问题根源
你测试失败的核心原因是:Fun类中的map1是私有静态成员,测试类里定义的map1是完全独立的另一个变量,两者没有任何关联。你在测试类中往自己的map1存入数据,根本不会影响Fun类内部的那个静态Map,所以调用foo方法时找不到"test"键,返回了默认的0L。
解决方案
方案1:修改Fun类设计(推荐)
把静态Map改成实例成员,并提供构造方法注入的方式,这样测试时可以直接传入自定义的Map,无需依赖静态变量,同时让代码更易维护和测试。
修改后的Fun类:
import java.util.HashMap; import java.util.Map; public class Fun { private Map<String,Long> map1; // 保留无参构造,兼容原有逻辑 public Fun() { this.map1 = new HashMap<>(); } // 测试专用构造方法,注入外部Map public Fun(Map<String, Long> map1) { this.map1 = map1; } public long foo(final String test){ if(!map1.containsKey(test)){ return 0L; } return map1.get(test); } }
对应的测试类:
import org.junit.Assert; import org.junit.Test; import java.util.HashMap; import java.util.Map; public class FunTest { @Test public void testfoo(){ Map<String, Long> testMap = new HashMap<>(); testMap.put("test", 2L); // 传入自定义的测试Map Fun classUndertest = new Fun(testMap); long value = classUndertest.foo("test"); Assert.assertEquals(2L, value); } }
方案2:通过反射修改静态成员(不推荐,仅当无法修改Fun类时使用)
如果不能改动业务类代码,可以用Java反射机制强制修改Fun类的静态map1字段,但这种方式会破坏封装性,且容易引发测试隔离问题(比如多个测试用例互相影响)。
修改后的测试类:
import org.junit.Assert; import org.junit.Test; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; public class FunTest { private Fun classUndertest = new Fun(); @Test public void testfoo() throws NoSuchFieldException, IllegalAccessException { // 获取Fun类的私有静态map1字段 Field mapField = Fun.class.getDeclaredField("map1"); mapField.setAccessible(true); // 创建测试用Map并赋值给静态字段 Map<String, Long> testMap = new HashMap<>(); testMap.put("test", 2L); mapField.set(null, testMap); // 静态字段set时第一个参数传null long value = classUndertest.foo("test"); Assert.assertEquals(2L, value); // 可选:测试完成后重置静态字段,避免影响其他测试 mapField.set(null, new HashMap<>()); } }
方案对比
- 方案1是最优解,通过依赖注入的方式消除了静态依赖,让代码更符合面向对象设计原则,测试也更灵活。
- 方案2是妥协方案,仅适用于无法修改业务代码的场景,使用时要注意测试隔离,避免静态状态污染后续测试。
内容的提问来源于stack exchange,提问作者Lark
相关产品推荐
相关产品推荐

