Mock Lambda表达式时遇ClassCastException及提取参数问题求助
问题解决:Hibernate doWork 类型转换异常及参数验证
异常情况
调用测试代码时出现类型转换异常:
java.lang.ClassCastException: com.paypal.compliance.data.process.eftns.dao.impl.EFTReportsDAO$$Lambda$9/170106909 cannot be cast to java.util.function.Consumer
对应的测试代码块:
when(session.doWork(any())).thenAnswer(invocation -> { Consumer<Connection> consumer = invocation.getArgument(0); consumer.accept(mockConnection); return null; });
核心原因
Hibernate Session.doWork() 方法接受的参数是**Work接口**(而非Consumer<Connection>),你传入的Lambda表达式实际实现的是Work接口,强行转成Consumer必然抛出类型转换异常。
另外你调试时看到的arg$1(SQL语句)和arg$2(EFTReportsDO列表)并非doWork方法的参数,而是Lambda捕获的外部变量,无法通过invocation.getArgument()直接提取。
解决方案
1. 修复类型转换异常
将测试中的类型转换改为Work接口,调用其execute方法:
when(session.doWork(any())).thenAnswer(invocation -> { // 正确获取Work实例,而非Consumer Work work = invocation.getArgument(0); work.execute(mockConnection); return null; });
2. 验证SQL语句与列表数据
若要验证SQL语句和批量更新的参数,可通过Mock对象的调用验证实现:
- 验证SQL语句是否正确传入:
verify(connection).prepareStatement(eq("UPDATE EFT_XYZ SET COMMENTS=?, PP_BATCH_SOURCE=?, WHERE PP_BATCH_ID=? AND REPORT_ID=?"));
- 验证批量参数是否正确设置(需给测试用的EFTReportsDO设置真实值):
// 验证第一个实体的参数设置 verify(preparedStatement).setString(1, eftReportsDO.getComments()); verify(preparedStatement).setString(2, eftReportsDO.getPpBatchSource()); verify(preparedStatement).setString(3, eftReportsDO.getId().getPpBatchId()); verify(preparedStatement).setString(4, eftReportsDO.getId().getReportId()); // 验证批量操作调用次数 verify(preparedStatement, times(1)).addBatch(); verify(preparedStatement, times(1)).executeBatch();
完整修正后的测试代码
@Test public void testMergeAllEftReports() throws SQLException { // Arrange List<EFTReportsDO> instanceList = new ArrayList<>(); EFTReportsDO eftReportsDO = new EFTReportsDO(); // 给实体设置测试用真实值 eftReportsDO.setComments("test comment"); eftReportsDO.setPpBatchSource("test source"); EFTReportsId id = new EFTReportsId(); id.setPpBatchId("batch123"); id.setReportId("report456"); eftReportsDO.setId(id); instanceList.add(eftReportsDO); when(entityManager.unwrap(Session.class)).thenReturn(session); Connection mockConnection = mock(Connection.class); PreparedStatement preparedStatement = mock(PreparedStatement.class); when(mockConnection.prepareStatement(anyString())).thenReturn(preparedStatement); // 修复类型转换问题 when(session.doWork(any())).thenAnswer(invocation -> { Work work = invocation.getArgument(0); work.execute(mockConnection); return null; }); // Act eftReportsDAO.mergeAllEftReports(instanceList); // Assert // 验证SQL语句正确性 verify(mockConnection).prepareStatement(eq("UPDATE EFT_XYZ SET COMMENTS=?, PP_BATCH_SOURCE=?, WHERE PP_BATCH_ID=? AND REPORT_ID=?")); // 验证参数设置 verify(preparedStatement).setString(1, "test comment"); verify(preparedStatement).setString(2, "test source"); verify(preparedStatement).setString(3, "batch123"); verify(preparedStatement).setString(4, "report456"); // 验证批量操作 verify(preparedStatement, times(1)).addBatch(); verify(preparedStatement, times(1)).executeBatch(); // 验证EntityManager的flush和close调用 verify(entityManager, times(1)).flush(); verify(entityManager, times(1)).close(); }
内容的提问来源于stack exchange,提问作者bon mohanty
相关产品推荐
相关产品推荐

