Lorsqu’on réalise nos tests unitaires, le SUT (system under test) interagit avec différents objets dont le comportement n’est pas à tester.
On peut prendre l’exemple d’une méthode qui aurait pour but d’effectuer des calculs puis envoyer un mail via un service d’envoi: il n’y a pas de valeur ajoutée à initialiser ce service, on voudrait simplement vérifier que la méthode “sendMail” soit appelée.
On voudrait également ne pas avoir à initialiser des objets complexes lorsque ceux-ci ne sont pas nécessaires. C’est lorsqu’on cherche comment arriver à cette fin qu’on tombe sur des termes comme “Mock” (le plus connu) mais aussi Spy, Fake, Dummy etc… Tous ces termes désignent des objets destinés à remplacer les objets réels afin de réaliser des tests.
L’objectif de cet article est d’expliquer les différences entre ces différents termes pour pouvoir utiliser l’outil le plus adapté à vos besoins 🙂
Note: les exemples seront réalisés en Java avec le framework Mockito mais les concepts restent les mêmes indépendamment du langage/framework 🙂
I. Définitions
Dummy
Un Dummy est simplement une structure d’objet qui va permettre de satisfaire un constructeur.
Quand l’utiliser ?
Si je dois initialiser un objet qui prend différents objets dans son constructeur et que certains d’entre eux ne me seront d’aucune utilité pour les tests, je peux les remplacer par des dummies pour éviter une instanciation fastidieuse sans valeur ajoutée.
Exemple d’utilisation:
Admettons que je veuille tester une méthode qui ne manipule que les offers et le receipt de ma classe Store ci-dessous, je n’ai aucun intérêt à initialiser un SupermarketCatalog qui ne servira pas dans mes tests.
Cet objet permettra de remplir le contrat, c’est-à-dire qu’il fera office de SupermarketCatalog dans le constructeur mais il n’a pas d’implémentation.
Si on imagine que je possède des receipt et offers instanciés, je pourrais alors écrire:
Store myStore = new Store(receipt, offers, supermarketCatalogDummy)
Cela permet de ne pas avoir à initialiser d’objets complexes lorsqu’ils ne sont pas nécessaires à la portion que nous voulons tester !
Fake
Un ‘fake’ est un objet simplifié qui sera plus facile à utiliser pour les tests. On pourrait citer l’exemple le plus courant d’une implémentation simplifiée d’une persistance d’objets. Peut être que dans la réalité, vous persistez des informations sur AWS dans un S3 mais que pour vos tests, sauvegarder des informations dans un SQLite ou une base H2 serait suffisant: si vous créez une implémentation qui le permet: c’est un fake.
Exemple d’utilisation:
J’ai un catalogue qui sauvegarde des produits dans une base de données et j’en ai besoin pour mes tests. Je peux faire implémenter l’interface de ce catalogue à un fake et interagir avec une Hashmap plutôt qu’une base de données réelle.
package dojo.supermarket.model;
import java.util.HashMap;
import java.util.Map;
public class FakeCatalog implements SupermarketCatalog {
private Map<String, Product> products = new HashMap<>();
private Map<String, Double> prices = new HashMap<>();
@Override
public void addProduct(Product product, double price) {
this.products.put(product.getName(), product);
this.prices.put(product.getName(), price);
}
@Override
public double getUnitPrice(Product p) {
return this.prices.get(p.getName());
}
}
Stub
Les “stubs” se substituent aux appels de méthode afin de donner des réponses pré-faites à des appels
Exemple d’utilisation:
Lorsque la portion que vous voulez tester doit obtenir des informations provenant de l’extérieur (via un service, une base de données etc..), vous voulez que cette information soit toujours la même indépendamment de l’état réel du service extérieur (BDD down par exemple).
Note: les Spies sont des stubs qui peuvent enregistrer leur état mais nous ne le détaillerons pas dans cet article.
Mock
Les mocks se substituent aux appels de méthodes pour faire des vérifications: on peut par exemple vérifier qu’une méthode a été appelée sans pour autant l’exécuter.
Exemple de cas d’utilisation:
Lorsque votre méthode appelle une API externe qui va se charger de persister un objet par exemple, vous pouvez avoir envie de vérifier que cette méthode soit appelée.
verify(ProductAPIService).save('toothBruch')
II. Pourquoi ces définitions ne vous disaient peut-être rien?
Mon explication c’est que lorsqu’on utilise un framework de test, on ne parle que de Mock: Mockito, EasyMock, Powermock…
En plus ces objets “Mock” peuvent endosser le rôle de Dummy, Stub, Mock.. Donc Mock est devenu dans le langage courant, un terme qui définit toutes les doublures de tests.
D’ailleurs dans l’exemple sur les Dummy, pour le créer on a utilisé la ligne de code suivante :
Cet article n’est qu’une porte d’entrée vers les doublures de tests, il est important d’avoir une idée (même simplifiée) de ces différents termes pour aller plus loin dans l’étude de celles-ci et d’améliorer leur utilisation dans notre quotidien.
Maintenant que vous avez lu cet article, je vous recommande d’aller lire sans plus attendre notre article “Dans quelles conditions utiliser des Mocks dans ses tests?” et spoil, pas aussi souvent qu’on pourrait le penser! 😀
Si vous souhaitez aller plus loin, je vous conseille de jeter un œil aux sources de cet article.
Description du problème
Par défaut, il n’est pas autorisé de faire des requêtes entre une application qui est dans un domaine A vers une autre qui serait dans un domaine B (pour des raisons de sécurité, il y a plus de détails dans les sources).
Si vous avez un front qui tourne sur un serveur node localhost:4200 et votre backend .Net sur localhost:7248), les requêtes du front ve...
On va créer pas-à-pas un raccourci qui nous permettra de générer un IBAN et de l’insérer à l’endroit où se trouve notre curseur. Si vous n’avez pas fait le setup pour développer un plugin Jetbrains, je vous invite à lire notre article sur le sujet.
...
Introduction
Vous utilisez un IDE Jetbrains et des fonctionnalités vous manquent par exemple:
des raccourcis bien pratiques
des fenêtres d’information
le support des formats de fichiers avec lesquels vous travaillez
etc..
Alors vous vous...
Votre changelog reprend les fonctionnalités que vous avez réalisé entre deux versions, ça tombe bien, votre historique git contient ces informations :) On va voir comment les extraire de git pour générer automatiquement un changelog exhaustif et fiable.
...