我有一个类,它连接到H2数据库并运行多个SQL语句。
public class H2Persistence implements IPersistence {
private Connection conn;
@Override
public void open() {
try
{
Class.forName("org.h2.Driver");
conn = DriverManager.getConnection(CONN_TYPE_USER_HOME);
final Statement stmt = conn.createStatement();
stmt.executeUpdate("CREATE TABLE PERSON(" +
"ID BIGINT,"+
"AGEGROUP VARCHAR(255),"+
"MONTHLY_INCOME_LEVEL VARCHAR(255)," +
"GENDER VARCHAR(1),"+
"HOUSEHOLD_ID BIGINT)");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
...
}
我想编写一个单元测试,用于验证在open
方法中执行某个SQL语句(DROP TABLE IF EXISTS PERSON
)。
为了做到这一点,我写了以下测试:
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest(DriverManager.class)
public class H2PersistenceTest {
@Test
public void testDropPersonIsCalled() throws SQLException {
final Statement statement = mock(Statement.class);
final Connection connection = mock(Connection.class);
when(connection.createStatement()).thenReturn(statement);
mockStatic(DriverManager.class);
when(DriverManager.getConnection(H2Persistence.CONN_TYPE_USER_HOME)).thenReturn
(connection);
final H2Persistence objectUnderTest = new H2Persistence();
objectUnderTest.open();
verify(statement.executeUpdate("DROP TABLE IF EXISTS PERSON"));
}
}
但它不起作用 - 而不是模拟连接,DriverManager
返回真正的连接。
如何修复它(在测试中使DriverManager
返回连接模拟?)
这是我项目的pom.xml
,也许出现了问题。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ru.mycompany</groupId>
<artifactId>myproduct</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<powermock.version>1.5.1</powermock.version>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-util</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert-core</artifactId>
<version>2.0M8</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.173</version>
</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-mockito</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
答案 0 :(得分:6)
这个有效(注意进口):
import static org.easymock.EasyMock.expect;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.powermock.api.easymock.PowerMock.mockStatic;
import static org.powermock.api.easymock.PowerMock.replay;
@RunWith(PowerMockRunner.class)
@PrepareForTest({DriverManager.class, H2Persistence.class})
public class H2PersistenceTest {
@Test
public void testDropPersonIsCalled() throws SQLException {
final Statement statement = mock(Statement.class);
final Connection connection = mock(Connection.class);
when(connection.createStatement()).thenReturn(statement);
mockStatic(DriverManager.class);
expect(DriverManager.getConnection(H2Persistence.CONN_TYPE_USER_HOME))
.andReturn(connection);
expect(DriverManager.getConnection(null))
.andReturn(null);
replay(DriverManager.class);
final H2Persistence objectUnderTest = new H2Persistence();
objectUnderTest.open();
verify(statement).executeUpdate("DROP TABLE IF EXISTS PERSON");
verify(statement).executeUpdate(H2Persistence.CREATE_TABLE_PERSON);
}
}
答案 1 :(得分:0)
执行此操作的常用方法是将连接创建分解为另一个类,并将该实例注入到相关类中。然后你可以模拟那个新类。
在你的情况下,像这样:
public class H2Persistence implements IPersistence {
private final ConnectionFactory connectionFactory;
private Connection conn;
public H2Persistence(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
@Override
public void open() {
try {
conn = connectionFactory.createConnection(CONN_TYPE_USER_HOME);
// etc
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
catch (SQLException e) {
e.printStackTrace();
}
}
}
public class ConnectionFactory {
Connection createConnection(String connType) throws SQLException, ClassNotFoundException {
Class.forName("org.h2.Driver");
return DriverManager.getConnection(connType);
}
}
在这种特殊情况下,更好的方法是使用标准JDBC接口DataSource
而不是您自己的连接工厂类:
public class H2Persistence implements IPersistence {
private final DataSource dataSource;
private Connection conn;
public H2Persistence(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public void open() {
try {
conn = dataSource.getConnection();
// etc
}
catch (SQLException e) {
e.printStackTrace();
}
}
}