Un constat…
Il est parfois tentant de définir des méthodes de ce genre pour ses tests unitaires :
Car dacia = new Car();
dacia.setSeats(4);
dacia.setColor("Red");
dacia.setWeight(1400);
dacia.setOwner("John Doe")
(...)
Et d’englober ça dans une méthode statique, puis de s’en servir pour ses tests.
Avec Instancio, il est possible d’éviter cela et d’utiliser une unique ligne pour votre test
// Given
Car c = Instancio.of(Car.class).create();
// Suite du test
⇒ Votre objet Car sera instancié avec toutes ses propriétés et sous-propriétés de façon aléatoire.
Imaginez maintenant le gain de lignes et de temps si l’objet Car disposait de 50+ propriétés !
Fonctionnalités
Génération basique d’objets
// Génère une voiture avec des données aléatoires :
Car car = Instancio.of(Car.class).create()
Génération de collections
// Génère une liste de 5 voitures aléatoires
List<Car> cars = Instancio.ofList(Car.class).size(5).create()
Spécifier des données à la génération
// Génère une voiture avec la couleur blanche uniquement
Car car = Instancio.of(Car.class).set(field(Car::getColor), "White").create()
// Génère une voiture avec un propriétaire respectant le pattern <nom prénom>
Car car = Instancio.of(Car.class).generate(field(Car::getOwner), gen -> gen.text().pattern("#s #s")).create()
Validation Jakarta & JPA
Par défaut, Instancio génère des données aléatoires sans respecter les éventuelles contraintes jakarta de validation.
Il est possible d’activer la validation des beans via une configuration spécifique.
Il est même possible de générer des données respectant les contraintes spécifiées par les annotations JPA.
Je trouve cela notamment très intéressant pour…
… des tests de mappers MapStruct
En couplant assertJ à Instancio, on peut réaliser des tests de non régressions très complets en 3 lignes :
// Given
Car expected = Instancio.of(HabilitationEntity.class).create();
// When
CarDto actual = mapper.convertEntityToDto(expected);
// Then
assertThat(actual).usingRecursiveComparison().isEqualTo(expected);
/* La comparaison récursive d'AssertJ sur des types différents
permettra de rapidement spotter des suppressions ou renommages de champs, évitant
ainsi des problèmes de mapping. Très efficace pour éviter les regressions. Il faudra jouer avec du 'withEnumStringComparison', 'ignoringFields(...)', etc. d'AssertJ afin de bien gérer la granularité de son test de mapper. */
… des tests unitaires de service
Pour avoir un objet cohérent et dynamique en entrée de la couche de service.
Mais ça ne sont pas les seules applications possibles d’Instancio, qui sont très nombreuses !
Limites
Attention cependant, les objets générés par Instancio étant aléatoires, à ne pas créer involontairement des flaky tests. Via IntelliJ par exemple, pour éviter ce souci, on peut exécuter un test N fois ou until failure.
Imaginons que votre objet généré via Instancio dispose d’un flag booléen ayant une influence sur l’exécution de votre méthode de service, lancer le code N fois peut permettre d’identifier cela.
C’est un risque avec Instancio, mais en même temps :
- Cela vous forcera à plus analyser et comprendre l’implémentation du service testé (dans un contexte de reprise projet, en testant du code que vous n’avez pas entièrement rédigé, que vous avez légèrement modifié et que vous souhaitez couvrir en tests)
- Et cela vous aidera à potentiellement identifier des comportements inattendus, du fait de l’unicité des jeux de données en entrée de service.
Leave a Reply