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

如何用Mockito模拟接口实现类中ResultSet返回空列表的测试场景?

问题排查与解决方案

核心问题分析

  • 注入冲突:同时使用@Autowired和@InjectMocks会导致Spring优先注入容器中真实的MyService实现类实例,Mockito的JdbcTemplate Mock无法被注入到目标对象,测试实际调用了真实数据库操作。
  • Mock匹配失效:when中传入的匿名RowMapper实例,和被测方法内部创建的RowMapper是两个不同对象,Mockito默认按对象相等性匹配,导致Mock条件永远不触发,无法返回预设的空列表。
  • 方向错误:无需模拟ResultSet,测试目标是**jdbcTemplate.query返回空列表时的判空逻辑**,直接Mockquery方法的返回值即可,不用关心RowMapper的具体执行。

修正后的测试代码

方案1:纯Mockito测试(不依赖Spring容器)

这种方式无需加载Spring上下文,测试速度更快,避免容器注入冲突:

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {

    @Mock
    private JdbcTemplate jdbcTemplate;

    @InjectMocks
    private MyAccessor myService; // 直接使用实现类

    @Test
    public void myTestMethod() {
        // 匹配任意SQL、任意RowMapper、任意参数,返回空列表
        Mockito.when(jdbcTemplate.query(
            Mockito.anyString(),
            Mockito.any(RowMapper.class),
            Mockito.anyString()
        )).thenReturn(Collections.emptyList());

        MyType result = myService.getMyMethod("value");
        assertEquals(0, result.getFieldA());
        assertEquals(0, result.getFieldB());
        assertEquals(0, result.getFieldC());
        assertEquals(0, result.getFieldD());
    }
}

方案2:结合Spring容器测试(替换容器中的JdbcTemplate为Mock)

如果必须依赖Spring上下文,用@MockBean替换容器中的真实实例:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { ".....", "....."})
@TestPropertySource(".....")
public class MyClassTest {

    @MockBean // 替换容器中的JdbcTemplate为Mock实例
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private MyService myService;

    @Test
    public void myTestMethod() {
        Mockito.when(jdbcTemplate.query(
            Mockito.anyString(),
            Mockito.any(RowMapper.class),
            Mockito.anyString()
        )).thenReturn(Collections.emptyList());

        MyType result = myService.getMyMethod("value");
        assertEquals(0, result.getFieldA());
        assertEquals(0, result.getFieldB());
        assertEquals(0, result.getFieldC());
        assertEquals(0, result.getFieldD());
    }
}

关键说明

  • 禁止@Autowired与@InjectMocks混用:前者是Spring注入注解,后者是Mockito的Mock注入注解,同时使用会引发注入优先级冲突。
  • 使用宽松匹配:用Mockito.any()系列方法(anyString()、any(Class.class))匹配参数,避免因匿名类、动态生成对象导致的匹配失败。
  • 聚焦测试目标:测试核心是验证空列表场景下的默认值返回逻辑,直接MockjdbcTemplate.query的返回值即可覆盖该场景,无需深入模拟ResultSet或RowMapper。

内容的提问来源于stack exchange,提问作者MinionAttack

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 11:21:31