Mockito中Lambda内connection.prepareStatement匹配失败返回Null问题
问题
使用Mockito进行测试时,已确认Connection已被正确Mock,但connection.prepareStatement无法匹配,返回的PreparedStatement为Null。
业务方法代码:
void myMethod(){ getJdbcTemplate().update(connection -> { PreparedStatement ps = connection.prepareStatement(addEmailData, new String[] { "mail_id" }); ps.setString(++i, mailBean.getFromEmailId()); return ps; }, keyHolder); }
测试用例代码:
void test(){ when(connection.prepareStatement(anyString(),any(String[].class))).thenReturn(mock(PreparedStatement.class)); when(dataSource.getConnection()).thenReturn(connection); myClass.init(dataSource); // Act myClass.myMethod(); }
解决方案
1. 确认Mock对象的一致性
确保测试中Mock的connection实例和JdbcTemplate回调里拿到的是同一个对象。如果getJdbcTemplate()内部有额外的connection获取逻辑,可能导致拿到的不是你Stub的那个Mock实例。
2. 调整参数匹配器
Mockito对数组类型的匹配可能存在兼容性问题,试试以下两种调整方式:
- 用通配匹配器替代数组类型匹配器:
when(connection.prepareStatement(anyString(), any())).thenReturn(mock(PreparedStatement.class)); - 如果测试时能确定传入的数组内容,用精确匹配:
when(connection.prepareStatement(anyString(), eq(new String[]{"mail_id"}))).thenReturn(mock(PreparedStatement.class));
3. 验证调用行为
添加验证代码,排查prepareStatement是否被正确调用,以及参数是否匹配:
// 验证方法是否被调用 verify(connection).prepareStatement(anyString(), any(String[].class)); // 或者验证具体参数 verify(connection).prepareStatement(eq(addEmailData), eq(new String[]{"mail_id"}));
如果验证失败,说明方法未被调用,或者参数和你Stub的不匹配。
4. 检查JdbcTemplate的回调上下文
在业务方法的回调逻辑中临时添加日志或断点,确认传入的connection实例是否为测试中Mock的对象,同时检查addEmailData变量的实际值是否和预期一致。
内容的提问来源于stack exchange,提问作者Ankur Singh
相关产品推荐
相关产品推荐

