Mock静态PreparedStatement方法测试CRUD时遇空指针异常求助
我来帮你梳理下这个问题的解决思路——你遇到的其实是PowerMock和Mockito版本不兼容导致的静态Mock失效问题,咱们一步步拆解:
问题场景回顾
你在测试数据库操作的deleteFoo方法时,想完全Stub掉StatementUtility的静态方法getFoo,避免执行原方法里创建PreparedStatement的逻辑,但不管换Mockito还是BDDMockito,调整参数匹配器、Mock Connection,都还是触发了原方法,抛出空指针异常。用的依赖是JUnit 4.12、Mockito 2.13.0、PowerMock 1.7.1。
核心原因:版本不兼容
这里的关键坑是PowerMock 1.7.x只兼容Mockito 1.x系列,根本不支持Mockito 2.x。你用的Mockito 2.13.0超出了PowerMock 1.7.1的兼容范围,导致静态Mock的拦截逻辑完全失效,原方法自然会被执行,进而引发空指针。
解决方案
方案1:降级Mockito到1.x(你已经验证有效)
把Mockito换成1.x的稳定版本,比如mockito-all:1.10.19,保持PowerMock 1.7.1不变,对应的PowerMock-Mockito依赖用powermock-mockito-1.7.1-full.jar,这样版本匹配上,静态Mock就能正常工作了。
方案2:升级PowerMock适配Mockito 2.x
如果不想降级Mockito,就把PowerMock升到支持Mockito 2.x的版本,比如用powermock-module-junit4:2.0.9 + powermock-api-mockito2:2.0.9,搭配Mockito 2.28.2这类兼容的2.x版本,这样也能解决版本冲突问题。
正确的静态Mock写法(以兼容版本为例)
顺便给你贴个标准的写法,确保配置和代码都没问题:
@RunWith(PowerMockRunner.class) @PrepareForTest(StatementUtility.class) // 必须指定要Mock的静态类,这步不能忘! public class DBConnectionBTBAdminTest { @Test public void deleteTest() throws SQLException { List<String> testInput = new ArrayList<>(); testInput.add("hello"); testInput.add("World"); // 先Mock Connection和PreparedStatement,避免空指针 Connection mockConn = PowerMockito.mock(Connection.class); PreparedStatement mockPstmt = PowerMockito.mock(PreparedStatement.class); PowerMockito.when(mockConn.prepareStatement(anyString())).thenReturn(mockPstmt); // 静态Mock StatementUtility.getFoo方法 PowerMockito.mockStatic(StatementUtility.class); BDDMockito.given(StatementUtility.getFoo(anyString(), eq(mockConn))).willReturn(mockPstmt); // 调用待测试方法 SomeClass.deleteCategory(testInput, new String[]{}); // 可选:验证静态方法是否被调用 PowerMockito.verifyStatic(StatementUtility.class); StatementUtility.getFoo(anyString(), eq(mockConn)); } }
几个关键注意点
- @PrepareForTest必须加对:一定要包含你要Mock的静态类
StatementUtility,不然PowerMock没法拦截静态方法调用。 - 参数匹配器要一致:Mock时用的匹配器(比如
anyString()、eq(mockConn))要和实际调用的参数类型、值匹配,不然会因为匹配失败走原方法逻辑。 - 先Mock依赖对象:先把Connection、PreparedStatement这些依赖Mock好,再作为静态方法的返回值,避免空指针。
内容的提问来源于stack exchange,提问作者kugtas

