J'ai une méthode DAO qui utilise Spring pour l'accès JDBC. Il calcule le taux de réussite d'un vendeur à vendre un article.
Voici le code:
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);
}
Comment dois-je procéder pour tester cette méthode ou toute méthode DAO avec JUnit? Quelles sont les meilleures pratiques pour tester la logique d'accès aux données? Je pense à le tester par rapport à une base de données embarquable chargée de certaines données, mais ne devrions-nous pas faire des tests d'intégration similaires à un environnement de production en termes de SGBDR et de schéma?
java
programming-practices
testing
tdd
Michael
la source
la source
Réponses:
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.
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é):
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
la source
sql.syntax_mys=true
qui changent le fonctionnement de hsqldb: "Cette propriété, lorsqu'elle est définie sur true, permet la prise en charge des types TEXT et AUTO_INCREMENT et permet également la compatibilité avec certains autres aspects de ce dialecte." whilesql.syntax_ora=true
"Cette propriété, lorsqu'elle est définie sur true, active la prise en charge des types non standard. Elle active également la syntaxe DUAL, ROWNUM, NEXTVAL et CURRVAL et permet également la compatibilité avec certains autres aspects de ce dialecte."Tout d'abord, vous ne devez jamais effectuer de tests dans un environnement de production. Vous devriez avoir un environnement de test qui reflète votre environnement de production et y faire des tests d'intégration.
Si vous faites cela, vous pouvez faire un certain nombre de choses.
la source
Sur notre projet, chaque développeur exécute une base de données vide, sa structure est la même que la base de données de production.
Dans chaque test unitaire TestInitialize, nous créons une connexion et une transaction à la base de données ainsi que certains objets par défaut dont nous avons besoin pour chaque test. Et tout est annulé après la fin de chaque méthode ou classe.
De cette façon, il est possible de tester la couche sql. En fait, chaque requête ou appel de base de données doit être testé de cette manière.
L'inconvénient est qu'il est lent, nous l'avons donc mis dans un projet distinct de nos tests unitaires réguliers. Il est possible d'accélérer cela en utilisant une base de données en mémoire, mais l'idée reste la même.
la source