Menguji Interaksi Pangkalan Data
Tulis ujian penyepaduan untuk lapisan capaian data bagi memastikan interaksi yang betul dengan pangkalan data hubungan.
Menguji Interaksi Pangkalan Data ialah pelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi merangkumi sejumlah 4 pelajaran.
Mengapa Menguji Interaksi Pangkalan Data?
Interaksi pangkalan data ialah bahagian penting bagi kebanyakan aplikasi. Menguji interaksi ini memastikan aplikasi anda menyimpan, mendapatkan semula dan mengemas kini data dengan boleh dipercayai.
- Integriti Data: Menjamin data disimpan dengan betul.
- Logik Perniagaan: Mengesahkan peraturan perniagaan berkaitan data.
- Pencegahan Ralat: Mengesan masalah sebelum masalah tersebut sampai ke persekitaran pengeluaran.
Cabaran Pangkalan Data Sebenar
Menguji secara langsung dengan pangkalan data pengeluaran sebenar boleh menjadi rumit dan menyebabkan ujian tidak boleh dipercayai:
- Perlahan: Pangkalan data sebenar menambah masa yang ketara kepada set ujian.
- Berkeadaan: Ujian boleh meninggalkan data lebihan yang menjejaskan ujian berikutnya.
- Persediaan Kompleks: Memerlukan perkhidmatan luaran yang sedang berjalan dan konfigurasi tertentu.
- Pengasingan: Sukar untuk memastikan setiap ujian dijalankan dalam persekitaran yang terasing.
Pangkalan Data Dalam Memori sebagai Penyelesaian
Untuk mengatasi cabaran ini, kita sering menggunakan pangkalan data dalam memori untuk ujian integrasi. Pangkalan data ini ringan dan berjalan sepenuhnya dalam memori aplikasi anda.
- Pantas: Tiada I/O cakera, dengan permulaan dan penutupan yang cepat.
- Terasing: Setiap pelaksanaan ujian boleh bermula dengan pangkalan data yang baharu dan kosong.
- Persediaan Mudah: Selalunya hanya memerlukan kebergantungan dan URL sambungan.
Pilihan popular termasuk H2, HSQLDB dan Apache Derby.
Menyediakan Pangkalan Data H2 Anda
Mari kita lihat betapa mudahnya untuk bersambung kepada pangkalan data dalam memori H2 menggunakan JDBC standard. Ia berfungsi seperti pangkalan data biasa, tetapi berada dalam memori aplikasi anda.
Anda memerlukan kebergantungan H2 (contohnya, Maven: com.h2database:h2).
import java.sql.*;
public class H2Demo {
public static void main(String[] args) throws SQLException {
String jdbcUrl = "jdbc:h2:mem:testdb";
String username = "sa";
String password = "";
try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) {
Statement stmt = conn.createStatement();
stmt.execute("CREATE TABLE products (id INT PRIMARY KEY, name VARCHAR(255))");
stmt.executeUpdate("INSERT INTO products (id, name) VALUES (1, 'Laptop')");
ResultSet rs = stmt.executeQuery("SELECT * FROM products");
if (rs.next()) {
System.out.println("Product: " + rs.getString("name"));
}
}
}
}Memperkenalkan Lapisan Akses Data
Aplikasi anda biasanya menggunakan corak Objek Akses Data (DAO) atau Repositori untuk berinteraksi dengan pangkalan data. Lapisan ini mengabstrakkan butiran JDBC atau ORM peringkat rendah.
Kami akan menggunakan ProductRepository yang mudah untuk mengurus objek Product.
public class Product {
private int id;
private String name;
public Product(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() { return id; }
public String getName() { return name; }
}
import java.util.List;
public interface ProductRepository {
void save(Product product);
Product findById(int id);
List<Product> findAll();
}Melaksanakan Repositori Mudah
Berikut ialah pelaksanaan asas ProductRepository kami menggunakan JDBC mentah. Dalam aplikasi sebenar, anda mungkin menggunakan JdbcTemplate Spring atau ORM seperti Hibernate.
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
// Product class and ProductRepository interface as defined previously
public class JdbcProductRepository implements ProductRepository {
private Connection conn;
public JdbcProductRepository(Connection conn) {
this.conn = conn;
try (Statement stmt = conn.createStatement()) {
stmt.execute("CREATE TABLE IF NOT EXISTS products (id INT PRIMARY KEY, name VARCHAR(255))");
} catch (SQLException e) { throw new RuntimeException(e); }
}
@Override
public void save(Product product) {
String sql = "INSERT INTO products (id, name) VALUES (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, product.getId());
ps.setString(2, product.getName());
ps.executeUpdate();
} catch (SQLException e) { throw new RuntimeException(e); }
}
@Override
public Product findById(int id) {
String sql = "SELECT id, name FROM products WHERE id = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, id); ResultSet rs = ps.executeQuery();
if (rs.next()) { return new Product(rs.getInt("id"), rs.getString("name")); }
} catch (SQLException e) { throw new RuntimeException(e); }
return null;
}
@Override
public List<Product> findAll() {
List<Product> products = new ArrayList<>();
String sql = "SELECT id, name FROM products";
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
products.add(new Product(rs.getInt("id"), rs.getString("name")));
}
} catch (SQLException e) { throw new RuntimeException(e); }
return products;
}
}Menguji Repositori - Persediaan
Sekarang, mari kita tulis program mudah untuk menguji JdbcProductRepository kami. Kami akan menyediakan pangkalan data dalam memori H2 khusus untuk pelaksanaan ujian ini.
Perhatikan bahawa kami mencipta sambungan pangkalan data baharu untuk repositori kami bagi memastikan pengasingan.
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
// Product class (simplified for mobile)
class Product {
private int id; private String name;
public Product(int id, String name) { this.id = id; this.name = name; }
public int getId() { return id; }
public String getName() { return name; }
}
// ProductRepository interface
interface ProductRepository {
void save(Product product);
Product findById(int id);
List<Product> findAll();
}
// JdbcProductRepository (simplified for mobile)
class JdbcProductRepository implements ProductRepository {
private Connection conn;
public JdbcProductRepository(Connection conn) {
this.conn = conn;
try (Statement stmt = conn.createStatement()) {
stmt.execute("CREATE TABLE IF NOT EXISTS products (id INT PRIMARY KEY, name VARCHAR(255))");
} catch (SQLException e) { throw new RuntimeException(e); }
}
@Override public void save(Product product) {
String sql = "INSERT INTO products (id, name) VALUES (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, product.getId()); ps.setString(2, product.getName());
ps.executeUpdate();
} catch (SQLException e) { throw new RuntimeException(e); }
}
@Override public Product findById(int id) { /* ... omitted ... */ return null; }
@Override public List<Product> findAll() { /* ... omitted ... */ return new ArrayList<>(); }
}
public class ProductRepositoryTestRunner {
public static void main(String[] args) throws SQLException {
String jdbcUrl = "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1";
try (Connection conn = DriverManager.getConnection(jdbcUrl, "sa", "")) {
System.out.println("DB connection established.");
ProductRepository repository = new JdbcProductRepository(conn);
Product laptop = new Product(1, "Laptop");
repository.save(laptop);
System.out.println("Saved product: " + laptop.getName());
Product foundProduct = repository.findById(1);
System.out.println("Found product: " + (foundProduct != null ? foundProduct.getName() : "None"));
List<Product> allProducts = repository.findAll();
System.out.println("Total products: " + allProducts.size());
}
}
}Mengesahkan Keadaan Pangkalan Data
Dalam ujian sebenar, sekadar mencetak hasil tidak mencukupi. Anda perlu membuat penegasan bahawa keadaan pangkalan data sepadan dengan jangkaan anda selepas sesuatu operasi. Ini mengesahkan bahawa kaedah DAO anda berfungsi dengan betul.
Mari tambahkan beberapa pemeriksaan asas untuk mengesahkan hasilnya.
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
// Product class (simplified for mobile)
class Product {
private int id; private String name;
public Product(int id, String name) { this.id = id; this.name = name; }
public int getId() { return id; }
public String getName() { return name; }
}
// ProductRepository interface
interface ProductRepository {
void save(Product product); Product findById(int id); List<Product> findAll();
}
// JdbcProductRepository (simplified for mobile)
class JdbcProductRepository implements ProductRepository {
private Connection conn;
public JdbcProductRepository(Connection conn) { /* ... omitted ... */ this.conn = conn; }
@Override public void save(Product product) { /* ... omitted ... */ }
@Override public Product findById(int id) {
String sql = "SELECT id, name FROM products WHERE id = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, id); ResultSet rs = ps.executeQuery();
if (rs.next()) { return new Product(rs.getInt("id"), rs.getString("name")); }
} catch (SQLException e) { throw new RuntimeException(e); }
return null;
}
@Override public List<Product> findAll() {
List<Product> products = new ArrayList<>();
String sql = "SELECT id, name FROM products";
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) { products.add(new Product(rs.getInt("id"), rs.getString("name"))); }
} catch (SQLException e) { throw new RuntimeException(e); }
return products;
}
}
public class ProductRepositoryAssertions {
public static void main(String[] args) throws SQLException {
String jdbcUrl = "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1";
try (Connection conn = DriverManager.getConnection(jdbcUrl, "sa", "")) {
ProductRepository repository = new JdbcProductRepository(conn);
Product laptop = new Product(1, "Laptop");
repository.save(laptop);
// Assertion 1: Check if product was saved
Product found = repository.findById(1);
if (found != null && found.getName().equals("Laptop")) {
System.out.println("Test Passed: Product saved & found.");
} else { System.out.println("Test Failed: Product not found or name mismatch."); }
// Assertion 2: Check total count
List<Product> all = repository.findAll();
if (all.size() == 1) {
System.out.println("Test Passed: Correct product count.");
} else { System.out.println("Test Failed: Incorrect product count."); }
}
}
}Memastikan Ujian Bersih dengan Transaksi
Untuk pengasingan ujian yang lebih kukuh, khususnya apabila menggunakan rangka kerja seperti Spring, anda boleh memanfaatkan transaksi.
Dengan menganotasi kaedah ujian anda menggunakan @Transactional, sebarang perubahan yang dibuat pada pangkalan data dalam ujian tersebut akan digulung balik secara automatik selepas ujian selesai. Ini meninggalkan pangkalan data dalam keadaan bersih untuk ujian seterusnya.
- Pembersihan Automatik: Tidak perlu menggunakan pernyataan
DELETEsecara manual. - Pengasingan: Setiap ujian dijalankan seolah-olah ia satu-satunya ujian.
- Lebih Pantas: Menggulung balik selalunya lebih pantas daripada memadam dan memasukkan semula data.
Amalan Terbaik Pengujian Pangkalan Data
Untuk menjadikan ujian integrasi pangkalan data anda berkesan dan mudah diselenggara, pertimbangkan petua berikut:
- Gunakan Pangkalan Data Dalam Memori: Untuk kelajuan dan pengasingan.
- Persediaan Minimum: Cipta hanya jadual dan data yang diperlukan untuk ujian tertentu.
- Ujian Transaksi: Gulung balik perubahan secara automatik.
- Penegasan Jelas: Sahkan data dan keadaan yang dijangka.
- Fokus pada DAO: Uji lapisan akses data, bukan logik perniagaan di sini.
Semakan Pantas: Pengujian Pangkalan Data
Antara berikut, yang manakah manfaat utama menggunakan pangkalan data dalam memori seperti H2 untuk ujian integrasi?
Imbas Kembali: Menguji Interaksi Pangkalan Data
Dalam pelajaran ini, kita mempelajari cara menguji interaksi pangkalan data dengan berkesan.
- Kami memahami cabaran menguji dengan pangkalan data sebenar.
- Kami menemui pangkalan data dalam memori seperti H2 sebagai penyelesaian yang pantas dan terasing.
- Kami melihat cara menyediakan dan berinteraksi dengan pangkalan data H2 secara terprogram.
- Kami berlatih menulis ujian untuk Objek Akses Data (DAO), bagi memastikan integriti data dan tingkah laku yang betul.
- Kami menyentuh tentang ujian transaksi untuk pembersihan automatik.
Teruskan berlatih untuk memastikan lapisan data aplikasi anda benar-benar kukuh!
Pelajari Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 12
- Pelajaran
- 48
Soalan Lazim
Adakah pelajaran “Menguji Interaksi Pangkalan Data” percuma?
Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi, termasuk “Menguji Interaksi Pangkalan Data”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Menguji Interaksi Pangkalan Data”?
Tulis ujian penyepaduan untuk lapisan capaian data bagi memastikan interaksi yang betul dengan pangkalan data hubungan. Anda berlatih Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.
Berapa lamakah pelajaran “Menguji Interaksi Pangkalan Data” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi ini?
Ya. Setiap pelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Ujian Unit berbanding Ujian Penyepaduan
- Menyediakan Ujian Penyepaduan
- Menguji Interaksi Pangkalan Data
- Menguji API Luaran dengan WireMock