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

如何在JUnit/Mockito单元测试中Mock DriverManager.getConnection方法

如何Mock DriverManager.getConnection方法

因为DriverManager.getConnection是静态方法,Mockito默认不支持mock静态方法,不过从Mockito 3.4.0版本开始,官方提供了mockStatic特性来处理这类场景,下面分两种方案给你说明:

方案一:直接Mock DriverManager静态方法

适合无法修改原有代码结构的场景,步骤如下:

1. 确保依赖版本

使用Mockito 3.4.0及以上版本(如果是Maven,pom.xml中依赖配置示例):

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>4.11.0</version>
    <scope>test</scope>
</dependency>

2. 测试代码示例

假设你有一个调用DriverManager.getConnection的工具类:

public class DatabaseUtil {
    public Connection getDbConnection(String url, String username, String password) throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }
}

对应的测试类:

import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import static org.mockito.Mockito.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DatabaseUtilTest {

    @Test
    void testGetDbConnection() throws SQLException {
        // 1. 创建mock的Connection对象
        Connection mockConn = mock(Connection.class);
        
        // 2. 用try-with-resources包裹MockedStatic,自动释放静态mock,避免影响其他测试
        try (MockedStatic<DriverManager> mockedDriverManager = mockStatic(DriverManager.class)) {
            // 3. 设定静态方法的调用行为:当传入任意参数时返回mock的Connection
            mockedDriverManager.when(() -> DriverManager.getConnection(anyString(), anyString(), anyString()))
                              .thenReturn(mockConn);
            
            // 4. 调用被测试方法
            DatabaseUtil util = new DatabaseUtil();
            Connection result = util.getDbConnection("jdbc:mysql://localhost/db", "test", "123456");
            
            // 5. 验证结果和调用行为
            assert result == mockConn;
            mockedDriverManager.verify(() -> DriverManager.getConnection("jdbc:mysql://localhost/db", "test", "123456"));
        }
    }
}

方案二:封装静态方法为可注入依赖(推荐)

静态方法的mock会让测试耦合度变高,更优雅的方式是把DriverManager的调用封装成接口,通过依赖注入的方式使用,这样完全不需要mock静态方法:

1. 重构原有代码

// 定义连接提供接口
public interface ConnectionProvider {
    Connection getConnection(String url, String username, String password) throws SQLException;
}

// 生产环境实现类,调用DriverManager
public class DriverManagerConnectionProvider implements ConnectionProvider {
    @Override
    public Connection getConnection(String url, String username, String password) throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }
}

// 修改工具类,通过构造注入依赖
public class DatabaseUtil {
    private final ConnectionProvider connectionProvider;

    public DatabaseUtil(ConnectionProvider connectionProvider) {
        this.connectionProvider = connectionProvider;
    }

    public Connection getDbConnection(String url, String username, String password) throws SQLException {
        return connectionProvider.getConnection(url, username, password);
    }
}

2. 测试代码示例

import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import java.sql.Connection;
import java.sql.SQLException;

public class DatabaseUtilTest {

    @Test
    void testGetDbConnectionWithProvider() throws SQLException {
        // mock接口实现和Connection对象
        ConnectionProvider mockProvider = mock(ConnectionProvider.class);
        Connection mockConn = mock(Connection.class);
        
        // 设定接口方法的返回行为
        when(mockProvider.getConnection(anyString(), anyString(), anyString())).thenReturn(mockConn);
        
        // 注入依赖并调用方法
        DatabaseUtil util = new DatabaseUtil(mockProvider);
        Connection result = util.getDbConnection("jdbc:mysql://localhost/db", "test", "123456");
        
        // 验证
        assert result == mockConn;
        verify(mockProvider).getConnection("jdbc:mysql://localhost/db", "test", "123456");
    }
}

注意事项

  • 方案二的代码结构更符合可测试性设计原则,后续维护和扩展更方便,优先推荐。
  • 如果使用JUnit 4,只需把测试注解换成org.junit.Test即可,核心mock逻辑不变。

内容的提问来源于stack exchange,提问作者User1515

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:16:08