Masalah dengan menggunakan database 'nyata' untuk pengujian unit adalah pengaturan, mencatat, dan isolasi tes. Anda tidak ingin harus memutar basis data MySQL yang sama sekali baru dan membuat tabel dan data hanya untuk satu tes unit. Masalah dengan ini berkaitan dengan sifat eksternal dari basis data dan basis data pengujian Anda turun, pengujian unit Anda gagal. Ada juga masalah dengan memastikan Anda memiliki database unik untuk pengujian. Mereka dapat diatasi, tetapi ada jawaban yang lebih sederhana.
Mengejek basis data adalah salah satu opsi namun tidak menguji kueri aktual yang dijalankan. Ini dapat digunakan sebagai solusi yang lebih sederhana ketika Anda ingin memastikan data dari DAO melewati sistem dengan benar. Tetapi untuk menguji DAO itu sendiri Anda memerlukan sesuatu di balik DAO memiliki data dan query berjalan dengan benar.
Hal pertama yang harus dilakukan adalah menggunakan basis data di memori. HyperSQL adalah pilihan yang sangat baik untuk ini karena memiliki kemampuan untuk meniru dialek database lain - sehingga perbedaan kecil antara database tetap sama (tipe data, fungsi dan sejenisnya). hsqldb juga memiliki beberapa fitur bagus untuk pengujian unit.
db.url=jdbc:hsqldb:file:src/test/resources/testData;shutdown=true;
Ini memuat keadaan database (tabel, data awal) dari testData
file. shutdown=true
akan secara otomatis mematikan basis data ketika koneksi terakhir ditutup.
Menggunakan injeksi ketergantungan , mintalah unit test memilih database yang berbeda dari apa yang digunakan produksi (atau tes, atau lokal).
DAO Anda kemudian menggunakan database yang disuntikkan di mana Anda dapat meluncurkan tes terhadap database.
Tes unit kemudian akan terlihat seperti (banyak hal yang membosankan tidak termasuk untuk singkatnya):
@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);
}
Dan dengan demikian, Anda punya tes unit yang memanggil DAO dan menggunakan data yang disiapkan dalam database on the fly yang ada selama durasi tes. Anda tidak perlu khawatir tentang sumber daya eksternal atau keadaan basis data sebelum menjalankan, atau mengembalikan ke kondisi yang diketahui (well, 'kondisi yang dikenal' adalah 'tidak ada' yang sepele untuk dikembalikan ke keadaan semula).
DBUnit dapat membuat banyak dari apa yang saya jelaskan sebagai proses yang lebih sederhana dalam mengatur basis data, membuat tabel dan memuat data. Jika Anda perlu menggunakan database aktual karena suatu alasan, sejauh ini ini adalah alat yang lebih baik untuk digunakan.
Kode di atas adalah bagian dari proyek pakar yang saya tulis untuk membuktikan konsep TestingWithHsqldb di github