Vấn đề với việc sử dụng cơ sở dữ liệu 'thực' để kiểm tra đơn vị là thiết lập, gỡ xuống và cách ly các bài kiểm tra. Bạn không muốn phải tạo ra một cơ sở dữ liệu MySQL hoàn toàn mới và tạo các bảng và dữ liệu chỉ cho một bài kiểm tra đơn vị. Các vấn đề với điều này phải làm với bản chất bên ngoài của cơ sở dữ liệu và cơ sở dữ liệu kiểm tra của bạn bị hỏng, kiểm tra đơn vị của bạn thất bại. Cũng có vấn đề với việc đảm bảo bạn có một cơ sở dữ liệu duy nhất để thử nghiệm. Họ có thể khắc phục, nhưng có một câu trả lời đơn giản hơn.
Mocking cơ sở dữ liệu là một tùy chọn tuy nhiên nó không kiểm tra các truy vấn thực tế đang chạy. Nó có thể được sử dụng như một giải pháp đơn giản hơn nhiều khi bạn muốn đảm bảo dữ liệu từ DAO đi qua hệ thống đúng cách. Nhưng để kiểm tra DAO, bạn cần một cái gì đó đằng sau DAO có dữ liệu và các truy vấn chạy đúng.
Điều đầu tiên cần làm là sử dụng một cơ sở dữ liệu bộ nhớ. HyperQuery là một lựa chọn tuyệt vời cho việc này vì nó có khả năng mô phỏng phương ngữ của cơ sở dữ liệu khác - do đó sự khác biệt nhỏ giữa các cơ sở dữ liệu vẫn giữ nguyên (kiểu dữ liệu, chức năng và tương tự). hsqldb cũng có một số tính năng hay để thử nghiệm đơn vị.
db.url=jdbc:hsqldb:file:src/test/resources/testData;shutdown=true;
Điều này tải trạng thái của cơ sở dữ liệu (các bảng, dữ liệu ban đầu) từ testData
tệp. shutdown=true
sẽ tự động tắt cơ sở dữ liệu khi đóng kết nối cuối cùng.
Sử dụng phép nội xạ phụ thuộc , yêu cầu các bài kiểm tra đơn vị chọn một cơ sở dữ liệu khác với những gì sản xuất (hoặc kiểm tra hoặc cục bộ) xây dựng sử dụng.
DAO của bạn sau đó sử dụng cơ sở dữ liệu được tiêm mà bạn có thể khởi chạy các kiểm tra đối với cơ sở dữ liệu.
Các bài kiểm tra đơn vị sau đó sẽ trông giống như (một loạt các công cụ nhàm chán không được bao gồm cho ngắn gọn):
@Before
public void setUpDB() {
DBConnection connection = new DBConnection();
try {
conn = connection.getDBConnection();
insert = conn.prepareStatement("INSERT INTO data (txt, ts, active) VALUES (?, ?, ?)");
} catch (SQLException e) {
e.printStackTrace();
fail("Error instantiating database table: " + e.getMessage());
}
}
@After
public void tearDown() {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private void addData(String txt, Timestamp ts, boolean active) throws Exception {
insert.setString(1, txt);
insert.setTimestamp(2, ts);
insert.setBoolean(3, active);
insert.execute();
}
@Test
public void testGetData() throws Exception {
// load data
Calendar time = Calendar.getInstance();
long now = time.getTimeInMillis();
long then1h = now - (60 * 60 * 1000); // one hour ago
long then2m = now - (60 * 1000 * 2); // two minutes ago
addData("active_foo", new Timestamp(then1h), true); // active but old
addData("inactive_bar", new Timestamp(then1h), false); // inactive and old
addData("active_quz", new Timestamp(then2m), true); // active and new
addData("inactive_baz", new Timestamp(then2m), false); // inactive and new
DataAccess dao = new DataAccess();
int count = 0;
for (Data data : dao.getData()) {
count++;
assertTrue(data.getTxt().startsWith("active"));
}
assertEquals("got back " + count + " rows instead of 1", count, 1);
}
Và do đó, bạn đã có một bài kiểm tra đơn vị gọi DAO và đang sử dụng dữ liệu được thiết lập trong cơ sở dữ liệu đang hoạt động trong suốt thời gian thử nghiệm. Bạn không phải lo lắng về tài nguyên bên ngoài hoặc trạng thái của cơ sở dữ liệu trước khi chạy hoặc khôi phục lại trạng thái đã biết (tốt, 'trạng thái đã biết' là 'không tồn tại', không quan trọng để hoàn nguyên).
DBUnit có thể thực hiện phần lớn những gì tôi đã mô tả một quy trình đơn giản hơn trong việc thiết lập cơ sở dữ liệu, tạo các bảng và tải dữ liệu. Nếu bạn sẽ cần phải sử dụng cơ sở dữ liệu thực tế vì một số lý do, đây là công cụ tốt hơn để sử dụng.
Đoạn mã trên là một phần của dự án maven mà tôi đã viết để chứng minh khái niệm TrialWithHsqldb trên github