如何在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
相关产品推荐
相关产品推荐

