Проблема використання «реальної» бази даних для тестування одиниць - це налаштування, зняття та ізоляція тестів. Вам не потрібно створювати абсолютно нову базу даних MySQL та створювати таблиці та дані лише для одного тестування одиниць. Проблеми з цим пов’язані із зовнішнім характером бази даних, і ваша тестова база даних знижена, ваші тестові одиниці не вдається. Також є проблеми із забезпеченням унікальної бази даних для тестування. Їх можна подолати, але є простіша відповідь.
Зміщення з базою даних є одним із варіантів, проте вона не перевіряє фактичні запущені запити. Він може бути використаний як набагато простіше рішення, коли ви хочете переконатися, що дані з DAO проходять через систему належним чином. Але для тестування самого DAO вам потрібно щось, за чим DAO має дані і запити виконуються належним чином.
Перше, що потрібно зробити - це використовувати в базі даних пам'яті. HyperSQL є прекрасним вибором для цього, оскільки він має можливість емуляції діалекту іншої бази даних - таким чином, незначні відмінності між базами даних залишаються однаковими (типи даних, функції тощо). hsqldb також має деякі приємні функції для тестування одиниць.
db.url=jdbc:hsqldb:file:src/test/resources/testData;shutdown=true;
Це завантажує стан бази даних (таблиці, початкові дані) testData
. shutdown=true
автоматично відключить базу даних, коли завершиться останнє з'єднання.
Використовуючи ін'єкцію залежності , попросіть одиничні тести вибрати іншу базу даних, ніж те, для чого використовують виробничі (або тестові, або місцеві).
Потім ваш DAO використовує введену базу даних, для якої можна запустити тести на базу даних.
Тоді одиничні тести будуть виглядати приблизно так (купа нудних речей, що не входять для стислості):
@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);
}
Таким чином, у вас є одиничний тест, який викликає DAO і використовує дані, встановлені в базі даних fly, яка існує протягом тривалості тесту. Вам не доведеться турбуватися про зовнішні ресурси або стан бази даних перед запуском або відновлення відомого стану (ну, "відомий стан" є "не існує", що тривіально для повернення).
DBUnit може зробити більшу частину того, що я описав, більш простим процесом у створенні бази даних, створенні таблиць та завантаженні даних. Якщо вам знадобиться чомусь використовувати фактичну базу даних, це набагато кращий інструмент для використання.
Вищевказаний код є частиною проекту Maven, який я написав для підтвердження концепції TestingWithHsqldb на github