You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:32:04