Aller au contenu
KésacoBackJavaTest

Gagnez du temps sur vos tests Java avec Instancio

Découvrez comment Instancio révolutionne la création d'objets pour vos tests Java en automatisant la génération de données aléatoires.

Instancio

On a tous connu ça : ce moment où, pour tester une petite règle métier, vous devez instancier un objet complexe avec 20 champs obligatoires, dont 5 objets imbriqués qui eux-mêmes demandent des paramètres... 😫 Résultat ? On se retrouve avec des lignes de code de préparation de test (Given) plus longues que le test lui-même.

Et si je vous disais qu'une librairie peut s'occuper de tout ça pour vous, tout en rendant vos tests plus robustes ? Laissez-moi vous présenter Instancio.

Késaco Instancio ?

Instancio est une librairie Java conçue pour générer automatiquement des objets remplis de données aléatoires. Son but est simple : éliminer le boilerplate lié à la création de données de test.

Contrairement à un simple constructeur ou un builder, Instancio va explorer l'arbre de dépendances de votre classe et remplir chaque champ avec une valeur cohérente (mais aléatoire) par défaut.

Pourquoi l'adopter ?

  1. Productivité boostée : vous ne créez que ce qui est pertinent pour votre test. Le reste est géré automatiquement.
  2. Robustesse accrue : en utilisant des données aléatoires, vous évitez le "biais du développeur" (tester toujours avec les mêmes chaînes "toto" ou "123"). Vous vous rapprochez naturellement du Property-Based Testing.
  3. Lisibilité : vos tests se concentrent sur l'intention métier, pas sur la tuyauterie.

Deep Dive : Instancio en action

Création simple : finis les new Person(...) interminables

Plus besoin de remplir manuellement chaque champ. Une seule ligne suffit :

@Test
void constructWithInstancio(){
    // Génère une instance de Person avec TOUS ses champs remplis aléatoirement
    final var person = Instancio.of(Person.class).create();
    
    System.out.println("Ma personne générée : " + person);
}

Puissance des Providers : maîtrisez l'aléatoire

Parfois, vous avez besoin de garder le contrôle sur certains champs tout en laissant le reste à l'aléatoire. Instancio propose une API fluide pour cela :

@ExtendWith(InstancioExtension.class)  
class MyTest {

    @Test
    void testWithCustomValue() {
        Person person = Instancio.of(Person.class)
            .set(field(Person::getFirstName), "Guillaume") // Je fixe le prénom
            .generate(field(Person::getAge), gen -> gen.ints().range(18, 99)) // Age réaliste
            .create();
            
        assertThat(person.getFirstName()).isEqualTo("Guillaume");
        assertThat(person.getAge()).isBetween(18, 99);
    }
}

Intégration JUnit 5 et 6 : @InstancioSource

C'est là que la magie opère pour se rapprocher du Property-Based Testing. Avec l'annotation @InstancioSource, vous pouvez exécuter le même test des centaines de fois avec des données différentes :

@DisplayName("❌ Devrait être invalide pour tout TIN avec moins de 6 chiffres")  
@ParameterizedTest(name = "exécution avec {0}")  
@InstancioSource(samples = 1000)  
void shouldBeInvalidForShorterTINs(FakeTaxInformation taxInformation) {  
  assertThat(validator.validate(taxInformation)).isNotEmpty();  
}

Ici, JUnit va lancer 1000 fois le test avec 1000 objets FakeTaxInformation différents. Si un cas aux limites fait échouer votre code, vous le saurez tout de suite ! 💪

Expressivité métier : créez vos propres annotations

C'est ici qu'Instancio brille vraiment. Au lieu d'utiliser des annotations génériques, vous pouvez créer vos propres annotations métier. Cela permet de rendre vos tests extrêmement lisibles : on ne teste plus une "String aléatoire", mais un "Numéro d'identification fiscale belge avec des caractères non-numériques".

Pour cela, on utilise l'interface GivenProvider.

Dans votre test, l'utilisation est limpide :

@RepeatedTest(1000)  
void shouldBeInvalidForTINsWithNonDigitCharacters(
    @ProvideTINWithNonDigitCharacters(countryCode = CountryCode.BE) 
    final FakeTaxInformation taxInformation) {  
  
  assertThat(validator.validate(taxInformation)).isNotEmpty();  
}

Et voici comment on câble la logique derrière l'annotation :

@Target({ElementType.FIELD, ElementType.PARAMETER})  
@Retention(RetentionPolicy.RUNTIME)  
@Given(TaxInformationWithNonDigitProvider.class)  
public @interface ProvideTINWithNonDigitCharacters {  
  
  CountryCode countryCode();  
  
  class TaxInformationWithNonDigitProvider implements GivenProvider {  
  
    @Override  
    public Object provide(final ElementContext elementContext) {  
      // On récupère les paramètres de l'annotation (ici le countryCode)
      final var annotation = elementContext.getAnnotation(ProvideTINWithNonDigitCharacters.class);  
  
      return Instancio.of(FakeTaxInformation.class)  
          .set(field(FakeTaxInformation::countryCode), annotation.countryCode())  
          // On génère spécifiquement un ID avec des caractères alphanumériques
          .generate(field(FakeTaxInformation::taxId), gen -> gen.string().alphaNumeric().length(11))  
          .create();  
    }  
  }  
}

Cette approche permet de réutiliser vos stratégies de génération de données complexes dans toute votre suite de tests tout en gardant une syntaxe déclarative élégante. 🎨

Instancio vs JQwik

Si vous voulez aller encore plus loin dans le test de propriétés, vous connaissez peut-être JQwik.

La différence ?

  • JQwik est un framework complet de Property-Based Testing (avec gestion des échecs, "shrinking", etc.).
  • Instancio est d'abord une librairie de génération de données qui peut servir à faire du Property-Based Testing très facilement au sein de JUnit 5.

Pour beaucoup de projets, Instancio est le "sweet spot" entre simplicité d'utilisation et puissance de test.

Conclusion : Le couteau suisse du testeur Java

Instancio est devenu pour moi un indispensable. Il réduit drastiquement la charge mentale lors de l'écriture des tests et permet de découvrir des bugs sournois grâce à l'aléatoire contrôlé.

Si vous voulez en savoir plus sur les stratégies de test chez SFEIR, n'hésitez pas à consulter nos articles sur sfeir.dev.


Points clés à retenir

  • 🛠️ Zéro boilerplate : génération automatique d'objets complexes.
  • 🎲 Aléatoire maîtrisé : API fluide pour fixer ou contraindre certaines valeurs.
  • 🚀 Intégration JUnit 5 : support natif pour les tests paramétrés avec @InstancioSource.
  • 💪 Robustesse : permet de détecter des edge cases difficiles à voir manuellement.

Alors, prêt à injecter un peu d'Instancio dans vos prochains tests ? 🚀

Dernier