如何使用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
相关产品推荐
相关产品推荐

