Le problème avec l'utilisation d'une «vraie» base de données pour les tests unitaires est la configuration, la suppression et l'isolement des tests. Vous ne voulez pas avoir à créer une base de données MySQL entièrement nouvelle et à créer des tables et des données juste pour un test unitaire. Les problèmes avec cela ont à voir avec la nature externe de la base de données et votre base de données de test est en panne, vos tests unitaires échouent. Il y a également des problèmes à vérifier que vous disposez d'une base de données unique pour les tests. Ils peuvent être surmontés, mais il existe une réponse plus simple.
Se moquer de la base de données est une option, mais il ne teste pas les requêtes réelles qui sont exécutées. Il peut être utilisé comme une solution beaucoup plus simple lorsque vous voulez vous assurer que les données du DAO passent correctement par le système. Mais pour tester le DAO lui-même, vous avez besoin de quelque chose derrière le DAO pour que les données et les requêtes s'exécutent correctement.
La première chose à faire est d'utiliser une base de données en mémoire. HyperSQL est un excellent choix pour cela car il a la capacité d'émuler le dialecte d'une autre base de données - de sorte que les différences mineures entre les bases de données restent les mêmes (types de données, fonctions, etc.). hsqldb a également quelques fonctionnalités intéressantes pour les tests unitaires.
db.url=jdbc:hsqldb:file:src/test/resources/testData;shutdown=true;
Cela charge l'état de la base de données (les tables, les données initiales) à partir du testData
fichier. shutdown=true
fermera automatiquement la base de données à la fermeture de la dernière connexion.
En utilisant de l'injection de dépendances , demandez aux tests unitaires de sélectionner une base de données différente de celle utilisée par les builds de production (ou test ou local).
Votre DAO utilise ensuite la base de données injectée pour laquelle vous pouvez lancer des tests sur la base de données.
Les tests unitaires ressembleront alors à quelque chose (tas de trucs ennuyeux non inclus pour plus de brièveté):
@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);
}
Et donc, vous avez un test unitaire qui appelle le DAO et utilise les données qui ont été configurées dans une base de données à la volée qui existe pour la durée du test. Vous n'avez pas à vous soucier des ressources externes ou de l'état de la base de données avant l'exécution, ou de la restauration à un état connu (enfin, «l'état connu» est «n'existe pas», ce qui est trivial pour revenir à).
DBUnit peut faire beaucoup de ce que j'ai décrit un processus plus simple dans la configuration de la base de données, la création des tables et le chargement des données. Si vous deviez utiliser la base de données réelle pour une raison quelconque, c'est de loin le meilleur outil à utiliser.
Le code ci-dessus fait partie d'un projet maven que j'ai écrit pour la preuve de concept TestingWithHsqldb sur github