Mock NamedParameterJdbcTemplate回调函数时返回null的问题排查
问题排查与修复方案
核心问题1:方法重载匹配错误
你的生产代码中调用的是NamedParameterJdbcTemplate.query的RowMapper重载版本:
List<LaAttributes> laAttributes = jdbcTemplate.query("Select_query", param, (rs, rowNum) -> new LaAttributes(rs.getString("cloumn1"), rs.getString("cloumn2")));
这里的第三个参数是RowMapper<LaAttributes>类型的lambda,但测试代码mock的是ResultSetExtractor重载版本,方法签名不匹配导致Mockito无法找到对应mock规则,最终返回null。
修复:将测试中的ResultSetExtractor替换为RowMapper,调整mock逻辑:
Mockito.when(mockedNamedParameterJdbcTemplate.query( Mockito.anyString(), Mockito.any(MapSqlParameterSource.class), Mockito.any(RowMapper.class) )).thenAnswer(invocation -> { RowMapper<LaAttributes> rowMapper = invocation.getArgument(2); ResultSet rs = Mockito.mock(ResultSet.class); // 注意和生产代码的列名拼写一致 Mockito.when(rs.getString("cloumn1")).thenReturn("column1"); Mockito.when(rs.getString("cloumn2")).thenReturn("column2"); // RowMapper的mapRow方法需要传入rowNum参数,传任意整数即可 return List.of(rowMapper.mapRow(rs, 1)); });
核心问题2:列名拼写不一致
生产代码中列名是"cloumn1"和"cloumn2"(拼写错误,少了字母m),但测试代码mock的是"column1"和"column2",这会导致rs.getString返回null,进而创建的LaAttributes对象属性为空。
修复:统一列名拼写——要么修正生产代码的列名为正确的"column1",要么让测试中的mock匹配生产代码的错误拼写"cloumn1"。
次要问题:Mockito参数匹配器语法错误
测试中的Mockito.anyString缺少括号,正确写法是Mockito.anyString(),语法错误会导致匹配失效或编译报错。
修复后的完整测试代码示例
@Test public void findFieldsByItemId() { List<String> itemsId = new ArrayList<>(); itemsId.add("VZ203"); Mockito.when(mockedNamedParameterJdbcTemplate.query( Mockito.anyString(), Mockito.any(MapSqlParameterSource.class), Mockito.any(RowMapper.class) )).thenAnswer(invocation -> { RowMapper<LaAttributes> rowMapper = invocation.getArgument(2); ResultSet rs = Mockito.mock(ResultSet.class); // 匹配生产代码的列名拼写 Mockito.when(rs.getString("cloumn1")).thenReturn("column1"); Mockito.when(rs.getString("cloumn2")).thenReturn("column2"); return List.of(rowMapper.mapRow(rs, 1)); }); List<LaAttributes> laAttributes = laAttributeRepo.findFieldByItemId(itemsId); Assert.assertEquals("column1", laAttributes.get(0).getColumnOne()); }
内容的提问来源于stack exchange,提问作者Sumit Kumar
相关产品推荐
相关产品推荐

