如何使用Mockito正确Mock自定义Map解决返回值类型错误
问题现象
使用Mockito对配置类的Map属性打桩时,抛出类型不匹配异常,期望打桩后返回自定义的Map实例,异常信息如下:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue: String cannot be returned by getTestMap2() getTestMap2() should return Map
原错误测试代码
@Mock private TestConfig testConfig; @Test public void testMapFunct() { Map<String, String> myMap = new HashMap<String, String>() {{put("a", "b");}}; when(testConfig.testMap2().get("test1")).thenReturn( myMap ); }
被测配置类代码
@Configuration @ConfigurationProperties(prefix = "map") @Data public class TestConfig { private Map<String, Long> testMap1; private Map<String, String> testMap2; }
关联配置文件
map: testMap1: test1: '1' test1: '2' test1: '3' testMap2: test1: "net1" test2: "net2" test3: "net3"
错误原因
- 打桩目标与返回值类型不匹配:
testConfig的testMap2属性是Map<String,String>类型,调用该Map的get("test1")方法返回值是String类型,但传入thenReturn的参数是Map实例,类型完全不匹配。 - 嵌套调用缺少前置打桩:普通
@Mock注解生成的代理对象,未手动打桩的方法默认返回null、基础类型默认值或空集合,直接写链式调用testConfig.testMap2().get()时,testMap2()的返回值本身未提前定义,会触发Mock的默认返回逻辑,抛出类型错误。
正确写法
根据需求分两种场景处理:
场景1:让testMap2整体返回自定义Map实例
如果你的目标是调用testConfig.getTestMap2()时,直接返回你构造的myMap对象,不需要做链式打桩,直接对testMap2的getter方法打桩即可,代码如下:
@Mock private TestConfig testConfig; @Test public void testMapFunct() { Map<String, String> myMap = new HashMap<String, String>() {{put("a", "b");}}; // 直接打桩testMap2的getter,返回自定义Map实例 when(testConfig.getTestMap2()).thenReturn(myMap); }
场景2:仅打桩testMap2中指定key的返回值
如果不需要替换整个testMap2,仅需要修改testMap2.get("test1")的返回值,需要开启Mock的深打桩模式,同时注意get方法返回String类型,传入的返回值也要是String类型,代码如下:
// 开启深打桩模式,支持链式调用打桩 @Mock(answer = Answers.RETURNS_DEEP_STUBS) private TestConfig testConfig; @Test public void testMapFunct() { // get方法返回String,thenReturn传入对应类型的返回值 when(testConfig.getTestMap2().get("test1")).thenReturn("自定义返回值"); }
内容的提问来源于stack exchange,提问作者lukaszFD
相关产品推荐
相关产品推荐

