Tôi có một lớp, kết nối với cơ sở dữ liệu H2 và chạy một số câu lệnh SQL.Làm thế nào để giả lập DriverManager.getConnection (...)?
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();
}
}
...
}
Tôi muốn viết một bài kiểm tra đơn vị, trong đó xác nhận, rằng trong phương pháp open
một câu lệnh SQL nào đó (DROP TABLE IF EXISTS PERSON
) được thực thi.
Để làm được điều này, tôi đã viết như sau kiểm tra:
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"));
}
}
Nhưng nó không hoạt động - thay vì kết nối giả, DriverManager
lợi nhuận kết nối thực.
Làm cách nào để khắc phục sự cố (làm cho DriverManager
trả về kết nối mô phỏng trong thử nghiệm)?
Đây là pom.xml
của dự án của tôi, có thể có sự cố ở đó.
<?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>
Tôi đã thực hiện việc này e (xem http://altruix.wordpress.com/portfolio/project-control-center/ để biết chi tiết). Vấn đề là nếu bạn viết rất nhiều các lớp bạn kết thúc với rất nhiều mã boilerplate (giao diện, giao diện nhà máy và triển khai của chúng). Vì vậy, tôi đã cố gắng để có được lợi thế của thiết kế đó (testability) mà không có chi phí (rất nhiều mã boilerplate). –
Đó chắc chắn là mối nguy hiểm khi thực hiện phương pháp này khi viết các thử nghiệm dựa trên giả. Tôi làm việc trên một codebase, nơi mà phần lớn logic đã được nghiền thành bột mịn bởi các millstones tái cấu trúc mô phỏng. Trong trường hợp này, cho rằng 'DataSource' đã tồn tại, đại diện cho một khái niệm khép kín, được định nghĩa rõ ràng, và đã triển khai, tôi sẽ nghĩ rằng nguy cơ phát triển quá mức của boilerplate là nhỏ. –