JUnit测试遇java.util.NoSuchElementException,如何Mock DriverManager.getConnection?
解决JUnit测试中DriverManager静态方法Mock及NoSuchElementException问题
问题背景
编写JUnit测试时调用DriverManager.getConnection触发了java.util.NoSuchElementException,原因是Databricks JDBC驱动在解析URL时,内部的StringTokenizer没有取到足够的token。目标是Mock该静态方法,避免访问实际数据库。
解决方案
方案1:重构代码(推荐,符合依赖注入原则)
把数据库连接逻辑封装成独立类,避免直接依赖静态方法,便于Mock:
- 新增数据库连接器类
public class DatabaseConnector { public Connection getConnection(String url, String user, String password) throws SQLException { return DriverManager.getConnection(url, user, password); } }
- 修改业务类,注入连接器依赖
public class DatabricksQueryExecutor { private final DatabaseConnector connector; // 通过构造方法注入依赖 public DatabricksQueryExecutor(DatabaseConnector connector) { this.connector = connector; } public String readUnityTableDataAsJson() throws SQLException { // 使用连接器获取连接,而非直接调用DriverManager Connection conn = connector.getConnection("your-url", "user", "pwd"); // 后续业务逻辑... return "mock-json-data"; } }
- 编写JUnit测试,Mock连接器
import org.junit.Test; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.junit.runner.RunWith; import java.sql.Connection; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class DatabricksQueryExecutorTest { @Mock private DatabaseConnector mockConnector; @Mock private Connection mockConnection; @Test public void testReadUnityTableDataAsJson() throws SQLException { // 配置Mock行为:调用getConnection时返回Mock的连接 when(mockConnector.getConnection(anyString(), anyString(), anyString())) .thenReturn(mockConnection); // 初始化被测试类,传入Mock的连接器 DatabricksQueryExecutor executor = new DatabricksQueryExecutor(mockConnector); // 执行测试方法 String result = executor.readUnityTableDataAsJson(); // 验证逻辑(示例) verify(mockConnector).getConnection(anyString(), anyString(), anyString()); // 可根据需要断言返回结果 // assertEquals("mock-json-data", result); } }
方案2:直接Mock DriverManager静态方法(适用于无法重构的场景)
需要使用Mockito-inline依赖(Mockito 3.4+版本支持静态方法Mock):
import org.junit.Test; import org.mockito.MockedStatic; import java.sql.Connection; import java.sql.DriverManager; import static org.mockito.Mockito.*; public class DatabricksQueryExecutorTest { @Test public void testReadUnityTableDataAsJson() throws SQLException { // 创建DriverManager的静态Mock,使用try-with-resources自动关闭 try (MockedStatic<DriverManager> mockedDriverManager = mockStatic(DriverManager.class)) { Connection mockConn = mock(Connection.class); // 配置静态方法的返回值 mockedDriverManager.when(() -> DriverManager.getConnection(anyString(), anyString(), anyString())) .thenReturn(mockConn); // 执行被测试方法 DatabricksQueryExecutor executor = new DatabricksQueryExecutor(); executor.readUnityTableDataAsJson(); // 验证静态方法是否被调用(可选) mockedDriverManager.verify(() -> DriverManager.getConnection(anyString(), anyString(), anyString())); } } }
报错原因说明
原报错是因为测试中传入的JDBC URL不符合Databricks驱动的解析要求,驱动内部用StringTokenizer拆分URL时没有足够的token,抛出NoSuchElementException。Mock静态方法后,会跳过驱动的实际解析逻辑,直接返回Mock的Connection,从而避免该异常。
内容的提问来源于stack exchange,提问作者User1515
相关产品推荐
相关产品推荐

