Saya memiliki metode DAO yang menggunakan Spring untuk akses JDBC. Ini menghitung tingkat keberhasilan penjual dalam menjual suatu barang.
Ini kodenya:
public BigDecimal getSellingSuccessRate(long seller_id) {
String sql = "SELECT SUM(IF(sold_price IS NOT NULL, 1, 0))/SUM(1)
FROM transaction WHERE seller_id = ?";
Object[] args = {seller_id};
return getJdbcTemplate().queryForObject(sql, args, BigDecimal.class);
}
Bagaimana cara saya menguji metode ini atau metode DAO dengan JUnit? Apa sajakah praktik terbaik untuk menguji logika akses data? Saya berpikir untuk mengujinya terhadap basis data yang dapat di-embed yang memuat beberapa data, tetapi bukankah kita harus melakukan tes integrasi yang mirip dengan lingkungan produksi dalam hal RDBMS dan skema?
java
programming-practices
testing
tdd
Michael
sumber
sumber
Jawaban:
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.
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):
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
sumber
sql.syntax_mys=true
yang mengubah cara hsqldb bekerja: "Properti ini, ketika disetel benar, memungkinkan dukungan untuk jenis TEXT dan AUTO_INCREMENT dan juga memungkinkan kompatibilitas dengan beberapa aspek lain dari dialek ini." sementarasql.syntax_ora=true
tidak "Properti ini, ketika disetel benar, memungkinkan dukungan untuk jenis non-standar. Ini juga memungkinkan sintaks DUAL, ROWNUM, NEXTVAL dan CURRVAL dan dan juga memungkinkan kompatibilitas dengan beberapa aspek lain dari dialek ini."Pertama, Anda tidak boleh melakukan pengujian di lingkungan produksi. Anda harus memiliki lingkungan pengujian yang mencerminkan lingkungan produksi Anda dan melakukan tes integrasi di sana.
Jika Anda melakukan itu, maka Anda dapat melakukan sejumlah hal.
sumber
Pada proyek kami, setiap pengembang menjalankan database kosong, strukturnya sama dengan database produksi.
Di setiap unit tes TestInitialize, kami membuat koneksi & transaksi ke database ditambah beberapa objek default yang kami butuhkan untuk setiap tes. Dan semuanya akan kembali setelah akhir setiap metode atau kelas.
Dengan cara ini, mungkin untuk menguji lapisan sql. Bahkan, setiap permintaan atau panggilan basis data harus diuji dengan cara ini.
Kelemahannya adalah lambat, jadi kami menempatkannya dalam proyek terpisah dari pengujian unit reguler kami. Dimungkinkan untuk mempercepat ini dengan menggunakan basis data dalam memori tetapi idenya tetap sama.
sumber