Dans le précédent article nous avons vu comment initialiser les mocks. Il est temps de voir comment les utiliser concrètement.
Notre classe de tests ressemble pour le moment à ça :
Votre test Mockito s'organisera de cette manière
Le stubbing
Mockito vous permet de créer des mocks, qui simulent le traitement des objets qui sont utilisés par la classe que vous voulez tester. Par défaut Mockito ne fait rien sur ces méthodes. On dit qu'elles ne sont pas stubbées (je reprends le terme de stub que l'on retrouve dans tous les articles en anglais). Vous avez un proxy qui vous renvoie une valeur correspondant à la nature de la donnée. Pour être plus clair, si votre méthode testée appelle une méthode d'un mock qui retourne normalement un int/Integer, Mockito renverra par défaut 0. Si le type est boolean/Boolean, la valeur par défaut est false. Dans les autres cas vous aurez null.
Dans l'exemple ci dessus je précise ce qu'il se passe lorsque j'appelle la méthode socialBroadcast
Si votre traitement ne se soucie pas de la valeur retournée ne vous embêtez pas à "stuber" les méthodes.
Dans mon cas le test pourrait être
Vérification des interactions
Une fois que le mock est créé, toutes les interactions sont tracées. Vous pouvez ainsi vérifier si votre mock a été appelé ou non.
Je ne trouve pas opportun de vérifier toutes les interactions. Car pour améliorer la maintenabilité d'un test dans le temps, il est préférable de faire des tests boites noires sans ce soucier du code à l'intérieur. Ceci permet de revoir votre implémentation sans avoir à reprendre sans cesse vos tests.
Mon code devient
Une question.... Qui a dit qu'écrire des tests utilisant des mocks était compliqué ?
Bon dans certains cas il est intéressant de vérifier certaines interactions. Par exemple si mon article n'est pas publier je peux vouloir être sûr qu'il n'a pas été envoyé aux réseaux sociaux
Nous savons maintenant comment initier, paramétrer et vérifier les mocks. Ces éléments vous permettront de vous débrouiller dans la plupart des cas. Mais il reste des choses à dire sur les mocks concernant BDD, les spy... Nous verrons ça dans un dernier article sur Mockito.
Merci à Agnes Crepet pour sa relecture
Notre classe de tests ressemble pour le moment à ça :
public class BlogArticleServiceImplTest { @InjectMocks private BlogArticleService blogArticleService = new BlogArticleServiceImpl(); @Mock private BlogExporterService mockElogExporterService; @Before public void setUp(){ MockitoAnnotations.initMocks(this); } @Test public void writeArticleShouldPublishAndBroadCast(){ } }
Organisation d'un test Votre test Mockito s'organisera de cette manière
- on indique comment se comportent nos mocks
- on appelle la méthode à tester
- on vérifie les résultats
@Test public void writeArticleShouldPublishAndBroadCast(){ //On prepare le mock when(mockElogExporterService.socialBroadcast(any(Article.class)))
.thenReturn(3); //On appelle notre classe boolean result = blogArticleService.write("title", "my new content"); //On vérifie que le mock a ete appele verify(mockElogExporterService).publish(any(Article.class)); verify(mockElogExporterService).socialBroadcast(any(Article.class)); assertThat(result).isEqualTo(true); }
Le stubbing
Mockito vous permet de créer des mocks, qui simulent le traitement des objets qui sont utilisés par la classe que vous voulez tester. Par défaut Mockito ne fait rien sur ces méthodes. On dit qu'elles ne sont pas stubbées (je reprends le terme de stub que l'on retrouve dans tous les articles en anglais). Vous avez un proxy qui vous renvoie une valeur correspondant à la nature de la donnée. Pour être plus clair, si votre méthode testée appelle une méthode d'un mock qui retourne normalement un int/Integer, Mockito renverra par défaut 0. Si le type est boolean/Boolean, la valeur par défaut est false. Dans les autres cas vous aurez null.
Dans l'exemple ci dessus je précise ce qu'il se passe lorsque j'appelle la méthode socialBroadcast
when(mockElogExporterService.socialBroadcast(any(Article.class)))et je "stube" cette méthode pour préciser ce qu'elle retournera quand elle sera utilisée
.thenReturn(3);
Vous pouvez également modifier le retour ("stub_er") d'une méthode pour lui faire retourner une exception
- méthode renvoyant une valeur
when(mockElogExporterService.socialBroadcast(any(Article.class)))
.thenThrow(new PublicationException("error"));
- méthode void
doThrow(new PublicationException("error"))
.when(mockElogExporterService).publish(any(Article.class));
Dans mon cas le test pourrait être
@Test public void writeArticleShouldPublishAndBroadCast(){ //On appelle notre classe
boolean result = blogArticleService.write("title", "my new content"); //On vérifie que le mock a ete appele verify(mockElogExporterService).publish(any(Article.class)); verify(mockElogExporterService).socialBroadcast(any(Article.class)); assertThat(result).isEqualTo(true); }
Vérification des interactions
Une fois que le mock est créé, toutes les interactions sont tracées. Vous pouvez ainsi vérifier si votre mock a été appelé ou non.
verify(mockElogExporterService).publish(any(Article.class)); verify(mockElogExporterService).socialBroadcast(any(Article.class));
Je ne trouve pas opportun de vérifier toutes les interactions. Car pour améliorer la maintenabilité d'un test dans le temps, il est préférable de faire des tests boites noires sans ce soucier du code à l'intérieur. Ceci permet de revoir votre implémentation sans avoir à reprendre sans cesse vos tests.
Mon code devient
@Test public void writeArticleShouldPublishAndBroadCast(){ //On appelle notre classe
assertThat(blogArticleService.write("title", "my new content").isEqualTo(true); }
Une question.... Qui a dit qu'écrire des tests utilisant des mocks était compliqué ?
Bon dans certains cas il est intéressant de vérifier certaines interactions. Par exemple si mon article n'est pas publier je peux vouloir être sûr qu'il n'a pas été envoyé aux réseaux sociaux
@Test public void writeArticleShouldNotBroadCastWhenArticleIsNotPublished(){ //On prepare le mock pour qu'il retourne une exception doThrow(new PublicationException("error"))
.when(mockElogExporterService).publish(any(Article.class)); //On appelle notre classe boolean result = blogArticleService.write("title", "my new content"); //On vérifie le résultat verify(mockElogExporterService, never()).socialBroadcast(any(Article.class)); assertThat(result).isEqualTo(false); }
Nous savons maintenant comment initier, paramétrer et vérifier les mocks. Ces éléments vous permettront de vous débrouiller dans la plupart des cas. Mais il reste des choses à dire sur les mocks concernant BDD, les spy... Nous verrons ça dans un dernier article sur Mockito.
Merci à Agnes Crepet pour sa relecture
Aucun commentaire:
Enregistrer un commentaire
Remarque : Seul un membre de ce blog est autorisé à enregistrer un commentaire.