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

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:

  1. 新增数据库连接器类
public class DatabaseConnector {
    public Connection getConnection(String url, String user, String password) throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }
}
  1. 修改业务类,注入连接器依赖
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";
    }
}
  1. 编写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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 23:35:57