Java SQLException:';未找到合适的驱动程序';当PowerMockito mockStatic DriverManager.class
我正在尝试mockStatic DriverManager.class并获取mockConnection,但真正的静态void方法被称为getConnection 测试类别:Java SQLException:';未找到合适的驱动程序';当PowerMockito mockStatic DriverManager.class,java,database-connection,powermock,powermockito,mockstatic,Java,Database Connection,Powermock,Powermockito,Mockstatic,我正在尝试mockStatic DriverManager.class并获取mockConnection,但真正的静态void方法被称为getConnection 测试类别: @RunWith(PowerMockRunner.class) @PrepareForTest(DriverManager.class) public class MyClassTest { @Before public void setUp() throws Exception { Connection
@RunWith(PowerMockRunner.class)
@PrepareForTest(DriverManager.class)
public class MyClassTest {
@Before
public void setUp() throws Exception {
Connection connection = mock(Connection.class);
Statement statement = mock(Statement.class);
PowerMockito.mockStatic(DriverManager.class);
PowerMockito.doReturn(connection).when(DriverManager.class, "getConnection", anyString(), anyString(), anyString());
}
@Test
public void testMain() {
// arrange
String[] args = {"name", "password", "database"};
}
}
Pom.xml
<properties>
<powermock.version>1.7.4</powermock.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
我做错了什么?如何正确模拟DriverManager.class?
另外,当我查看org.powermock.api.mockito.internal.expectation.powermockitostuberimpl.When(powermockitostuberimpl.java:110)时,我发现它总是调用“Whitebox.invokeMethod(classMock,methodToExpect,parameters);”因此,我不理解它一般是如何工作的。作为初始化的一部分,
DriverManager
类将尝试加载系统属性“jdbc.drivers”
中引用的驱动程序类。这在加载DriverManager
类时发生,即在调用getConnection()
之类的任何方法之前。因此,您得到的异常并不是因为调用了真正的getConnection()
。这是因为在类路径上没有包含真正的驱动程序类,pom
可以明显看出,DriverManager
可以在初始化期间加载。因此,请在您的pom
中包含一个驱动程序,然后再试一次
请参阅和位于的DriverManager类源代码中的
静态块。当我创建objectUnderTest实例并将其类名置于@PrepareForTest注释下时,最终有效的解决方案(忽略out控制台中的警告)。虽然我不知道为什么会这样:
@RunWith(PowerMockRunner.class)
@PrepareForTest(DriverManager.class, MyClass.class)
public class MyClassTest {
@Before
public void setUp() throws Exception {
Connection connection = mock(Connection.class);
Statement statement = mock(Statement.class);
PowerMockito.mockStatic(DriverManager.class);
PowerMockito.when(DriverManager.getConnection(anyString(), anyString(), anyString())).thenReturn(connection);
}
@Test
public void testMain() {
// arrange
String[] args = {"name", "password", "database"};
MyClass myClass = new MyClass();
myClass.method();
...
}
好的,我添加了缺少的依赖项,并像这样重写了setupMock:PowerMockito.mockStatic(DriverManager.class);当(DriverManager.getConnection(anyString(),anyString(),anyString()),然后返回(conn);但当我试图运行DriverManager.registerDriver(new oracle.jdbc.OracleDriver())时,出现了一个新的异常“java.lang.LinkageError:loader约束冲突:loader(org/powermock/core/classloader/MockClassLoader的实例)先前启动了另一种类型的加载”;看起来DriverManager根本没有被嘲笑过。你有什么想法吗?DriverManager和要注册的驱动程序都应该由同一个类加载器加载。在您的例子中,DriverManager由MockClassLoader加载,驱动程序oracle.jdbc.OracleDriver由JVM自己的类加载器加载。为什么要包含语句DriverManager.registerDriver(new oracle.jdbc.OracleDriver()?是否确实要以编程方式加载oracle驱动程序?DriverManager.registerDriver()通常由驱动程序自己在新加载时调用。请参阅。谢谢你,Sanjeev,现在已经清楚了。关于你的问题“为什么要包含语句DriverManager.registerDriver(new oracle.jdbc.OracleDriver()”:不幸的是,这不是我的代码,它是在我需要创建单元测试的类中硬编码的。
@RunWith(PowerMockRunner.class)
@PrepareForTest(DriverManager.class, MyClass.class)
public class MyClassTest {
@Before
public void setUp() throws Exception {
Connection connection = mock(Connection.class);
Statement statement = mock(Statement.class);
PowerMockito.mockStatic(DriverManager.class);
PowerMockito.when(DriverManager.getConnection(anyString(), anyString(), anyString())).thenReturn(connection);
}
@Test
public void testMain() {
// arrange
String[] args = {"name", "password", "database"};
MyClass myClass = new MyClass();
myClass.method();
...
}