如何在JUnit 5中Mock JdbcTemplate.query方法的数组参数?
JdbcTemplate方法Mock失败的问题解决
你要Mock的JdbcTemplate方法如下:
public <T> List<T> query(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper) throws DataAccessException { return result(query(sql, args, argTypes, new RowMapperResultSetExtractor<>(rowMapper))); }
你尝试的Mock代码未生效:
when(db.query(anyString(), any(Object[].class), any(int[].class), new IdRowMapperImpl())).thenReturn(profileIds);
问题根源
- RowMapper实例不匹配:你直接用
new IdRowMapperImpl()作为匹配参数,Mockito默认用对象的equals方法判断匹配,但实际代码中传入的RowMapper实例和你这里new的不是同一个对象,导致匹配失败。 - 数组匹配的潜在问题:虽然
any(Object[].class)和any(int[].class)能匹配任意数组,但部分场景下Mockito对数组类型的匹配需要更灵活的处理。
正确Mock写法
方式1:用类型匹配器匹配RowMapper
把new IdRowMapperImpl()换成类型匹配器,让Mockito匹配任意该类型的实例:
// 匹配IdRowMapperImpl类型的任意实例 when(db.query(anyString(), any(Object[].class), any(int[].class), any(IdRowMapperImpl.class))) .thenReturn(profileIds); // 如果不需要限定子类,匹配任意RowMapper实例更通用 when(db.query(anyString(), any(Object[].class), any(int[].class), any(RowMapper.class))) .thenReturn(profileIds);
方式2:精准匹配数组内容(如果需要)
如果要匹配特定的数组内容,结合Hamcrest的arrayEquals匹配器和Mockito的argThat:
import org.hamcrest.Matchers; // 定义预期的数组内容 Object[] expectedArgs = new Object[]{1001, "admin"}; int[] expectedArgTypes = new int[]{java.sql.Types.INTEGER, java.sql.Types.VARCHAR}; when(db.query(anyString(), argThat(Matchers.arrayEquals(expectedArgs)), argThat(Matchers.arrayEquals(expectedArgTypes)), any(IdRowMapperImpl.class))) .thenReturn(profileIds);
方式3:简化匹配逻辑
如果不需要限定数组类型,直接用any()匹配任意参数,写法更简洁:
when(db.query(anyString(), any(), any(), any(IdRowMapperImpl.class))) .thenReturn(profileIds);
额外注意点
- 确保
db是通过Mockito.mock(JdbcTemplate.class)创建的Mock对象,而非真实实例。 - 如果方法调用时存在
null参数,要用isNull()匹配器替代any()。
内容的提问来源于stack exchange,提问作者mal
相关产品推荐
相关产品推荐

