Mockito – Présentation

Qu’est-ce que Mockito ?

Pour comprendre Mockito, il faut d’abord comprendre ce qu’est un test unitaire.

Un test unitaire consiste à ne tester qu’une et qu’une seule méthode à la fois. On ne s’occupe pas de l’implémentation des autres méthodes, à la place on simule leur comportement selon notre cas de test. Ainsi si on appelle une méthode de calcul, celle-ci peut soit retourner la valeur 1, 2 ou n’importe quoi, cela dépend de ce que nous définissons comme résultat attendu dans notre test lorsque nous appelons cette méthode de calcul.

Mockito est un framework de test qui permet de bouchonner les classes autres que celle à tester et de définir des comportements sur leurs méthodes afin de répondre aux cas de test.

Cet article présente les différents cas possibles de comportements qui peuvent être définies sur des méthodes à simuler. Mais avant cela il est important de comprendre que la classe sur laquelle nous posons des comportements doit être mockée.

Mocker la classe à simuler

Définir des comportements sur des méthodes implique que la classe ait été mockée via Mockito. C’est à dire que nous n’utilisons pas la vraie classe mais une classe définie par Mockito qui reprend les mêmes méthodes que la vraie classe.

Nous pouvons alors définir des comportements sur les méthodes de la classe mockée, comme par exemple retourner un résultat spécifique en fonction des valeurs qui lui sont passées en paramètre.

La syntaxe suivante permet de mocker une classe via Mockito :

Mockito.mock(Meteo.class);

, avec : Meteo : la classe à mocker.

Avec la ligne suivante, la variable meteo contient le mock de la classe Meteo :

Meteo meteo = Mockito.mock(Meteo.class);

Puisque nous avons mocké cette classe, nous pouvons maintenant définir le comportement attendue pour l’appel d’une des méthodes de cette classe.

Définir des comportements

Les chapitres suivants présentent les comportements de base qui peuvent être définis sur les méthodes d’une classe mockée:

Comportement 1 : Une méthode sans paramètre retourne toujours la même valeur

Par exemple, la méthode à tester appelle la méthode Meteo.getTemperatureActuelle() qui retourne la température actuelle. Nous pouvons simuler le résultat via la syntaxe suivante de Mockito dans notre test afin qui cette méthode retourne toujours 10 comme température :

Mockito.when(meteo.getTemperatureActuelle()).thenReturn(10);

Cette syntaxe implique que la classe Meteo a été mockée via Mockito, via la syntaxe suivante ou par annotation :

Meteo meteo = Mockito.mock(Meteo.class);

Mockito.when(meteo.getTemperatureActuelle()).thenReturn(10);

Comportement 2 : La méthode avec paramètres retourne une valeur en fonction de ses paramètres

Nous souhaitons maintenant que le résultat retourné par la méthode mockée varie en fonction du ou des paramètres.

Nous prenons comme exemple une méthode qui retourne la température prévue dans les prochains jours en passant en paramètre le numéro du jour par rapport à aujourd’hui, avec « 0 » pour aujourd’hui, « 1 » pour demain, « 2 » pour le surlendemain, etc.

Nous souhaitons que cette méthode retourne « 10 » pour aujourd’hui, « 8 » pour demain et « 9 » pour le surlendemain :

Mockito.when(meteo.getTemperature(0)).thenReturn(10);
Mockito.when(meteo.getTemperature(1)).thenReturn(8);
Mockito.when(meteo.getTemperature(2)).thenReturn(9);

Le paramètre peut également être un objet.

Mockito se base alors sur la méthode « equals » de cet objet pour savoir si l’instance actuellement passée en paramètre est égale à celle utilisée lors de la définition du comportement.

Par exemple, nous n’utilisons pas la même instance de la classe « Jour » pour définir le comportement et lors de l’appel de la méthode :

Jour jourDemain = new Jour();
jourDemain.setNumeroJour(1);
Mockito.when(meteo.getTemperature(jourDemain)).thenReturn(8);

Jour jourTest = new Jour();
jourTest.setNumeroJour(1);
Assert.assertEquals(8, meteo.getTemperature(jourTest));

Les deux instances de Jour « jourDemain » et « jourTest » contiennent tous les deux la valeur « 1 » pour « numeroJour ». Comme la méthode « equals » de la classe Jour retourne « vrai » si les deux instances ont le même « numeroJour » alors la vérification « assertEquals » est correcte : la température retournée est bien 8.

Comportement 3 : la méthode ne retourne pas de valeur => nous vérifions qu’elle a été appelée

Dans le cas où la méthode ne retourne pas de valeur (méthode « void »), nous pouvons vérifier qu’elle a bien été appelée. Cette vérification ne doit se faire qu’après l’appel de la méthode de test.

Nous prenons comme exemple la méthode « saveTemperature » qui enregistre la température pour un numéro de jour donné par rapport à aujourd’hui. Nous souhaitons vérifier que la température « 8 » a bien été enregistrée pour demain, c’est à dire pour « numeroJour » égal à « 1 » :

Meteo meteo = Mockito.mock(Meteo.class);

// Enregistrement de la température
meteo.saveTemperature(1, 8);

// Vérifier que l'enregistrement a été effectué
Mockito.verify(meteo).saveTemperature(1, 8);

La méthode « verify » de Mockito prend en paramètre la classe mockée (meteo). Nous vérifions que la méthode « saveTemperature » a bien été appelée en appelant celle-ci à partir de l’instance « Meteo » retournée par la méthode « verify ».

Nous pouvons également qu’une méthode n’a jamais été appelée via la syntaxe suivante ou on ajoute « Mockito.never() » comme deuxième paramètre de la méthode « Mockito.verify() » :

// Vérifier que l'enregistrement n'a pas été effectué
Mockito.verify(meteo, Mockito.never()).saveTemperature(1, 8);

Dans le cas où la méthode prend en paramètre des objets, Mockito se base alors sur la méthode « equals » des objets en paramètre pour vérifier si l’instance en paramètre est égale à celle utilisée lors de la définition du comportement.

Nous prenons comme exemple l’utilisation de la classe « Jour » qui contient le numéro de jour par rapport à aujourd’hui. La méthode « Jour.equals » se base sur la propriété « numeroJour » pour savoir si deux jours sont égaux et retourne alors « vrai ».

Meteo meteo = Mockito.mock(Meteo.class);

Jour jourDemain = new JourDemain();
jourDemain.setNumeroJour(1);

// Enregistrement de la température
meteo.saveTemperature(jourDemain, 8);

// Vérifier que l'enregistrement a été effectué
Jour jourTest = new Jour();
jourTest.setNumeroJour(1);
Mockito.verify(meteo).saveTemperature(jourTest, 8);

Les deux instances Jour sont différentes mais comme la méthode « equals » retourne vrai, Mockito saura qu’il s’agit du même paramètre et donc du même appel à la méthode « saveTemperature ».

Comportement 4 : La méthode lève une exception

Nous pouvons définir comme comportement que la méthode lève une exception.

La définition de ce comportement change en fonction de la méthode, à savoir si elle retourne une valeur ou non et si elle prend des paramètres.

Dans le cas où la méthode ne prend de paramètre et retourne une valeur :

Mockito.when(meteo.getTemperature()).thenThrow(exception);

Dans le cas où la méthode prend des paramètres et retourne une valeur :

Mockito.when(meteo.getTemperature(1, 8)).thenThrow(exception);

Dans le cas où la méthode ne retourne pas de valeur :

Mockito.doThrow(exception).when(meteo).saveTemperature(1, 8);

Conclusion

Nous avons dans cette introduction comment mocker une classe et les comportements les plus courants que nous pouvons définir sur les méthodes de la classe mockée.

Ceci permet de commencer à écrire de vrais tests unitaires à l’aide de bouchons via Mockito, dont voici un exemple complet :

Tagged with:
Publié dans Mockito

Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google

Vous commentez à l’aide de votre compte Google. Déconnexion /  Changer )

Image Twitter

Vous commentez à l’aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s

%d blogueurs aiment cette page :