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

如何使用TestNG覆盖JdbcTemplate.call方法中的connection.prepareCall逻辑

使用TestNG测试JdbcTemplate.call内的connection.prepareCall逻辑

要覆盖Test方法中JdbcTemplate.call回调里的connection.prepareCall逻辑,我们可以结合TestNG和Mockito模拟依赖,避免真实数据库交互,具体步骤如下:

1. 准备依赖

确保项目中引入TestNG和Mockito的依赖(以Maven为例):

<dependencies>
    <!-- TestNG测试框架 -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.8.0</version>
        <scope>test</scope>
    </dependency>
    <!-- Mockito模拟工具 -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>5.6.0</version>
        <scope>test</scope>
    </dependency>
    <!-- Spring测试辅助(若使用Spring环境) -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>6.0.11</version>
        <scope>test</scope>
    </dependency>
</dependencies>

2. 编写测试类

假设包含待测试Test方法的业务类名为MyService,测试类实现如下:

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcTemplate;
import java.sql.CallableStatement;
import java.sql.Connection;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

public class MyServiceTest {
    // 模拟JdbcTemplate,避免真实数据库操作
    @Mock
    private JdbcTemplate jdbcTemplate;

    // 将模拟对象注入被测试类实例
    @InjectMocks
    private MyService myService;

    @BeforeMethod
    public void setUp() {
        // 初始化Mockito注解
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void testPrepareCallAndParameterSetting() throws Exception {
        // 1. 模拟Connection和CallableStatement对象
        Connection mockConnection = mock(Connection.class);
        CallableStatement mockStmt = mock(CallableStatement.class);

        // 2. 定义模拟行为:调用prepareCall时返回模拟的Statement
        when(mockConnection.prepareCall(MyService.spalphabets)).thenReturn(mockStmt);

        // 3. 拦截JdbcTemplate.call,触发回调逻辑
        doAnswer(invocation -> {
            // 获取回调参数(ConnectionCallback实现)
            ConnectionCallback<?> callback = invocation.getArgument(0);
            // 传入模拟Connection,执行回调内的代码
            callback.doInConnection(mockConnection);
            // 模拟JdbcTemplate.call的返回值,可根据业务调整
            return null;
        }).when(jdbcTemplate).call(any(ConnectionCallback.class), any());

        // 4. 调用待测试方法
        myService.Test(123);

        // 5. 验证核心逻辑是否正确执行
        verify(mockConnection).prepareCall(MyService.spalphabets);
        verify(mockStmt).setInt(1, 123);
        verify(mockStmt).setString(2, "apple"); // 对应原代码的String.valueOf("apple")
    }
}

关键说明

  • 依赖模拟:用Mockito创建JdbcTemplate、Connection、CallableStatement的模拟对象,完全隔离真实数据库环境。
  • 回调触发:通过doAnswer拦截JdbcTemplate.call的调用,手动执行回调逻辑并传入模拟Connection,覆盖回调内的prepareCall、参数设置代码。
  • 逻辑验证:用verify方法确认prepareCall是否使用了正确的存储过程名,setInt、setString是否传入了预期参数值。

额外注意事项

  • 若spalphabets是私有静态变量,可通过反射获取其值用于验证,或临时调整为包私有权限简化测试。
  • 若getValue()方法存在外部依赖,需同步模拟该方法,避免干扰测试流程。
  • 若需验证返回的testResponse,可调整doAnswer的返回值为模拟结果,再断言方法返回值是否符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 05:12:46