FAQ Tests Consultez toutes les FAQ
Nombre d'auteurs : 2, nombre de questions : 40, dernière mise à jour : 31 décembre 2017 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums de http://www.developpez.com et de l'expérience personnelle des auteurs.
Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.
- Comment installer Mockito ?
- Comment créer un mock avec Mockito ?
- Comment prédire le résultat d'une méthode via Mockito ?
- Comment faire une assertion sur l'appel d'une méthode avec Mockito ?
- Comment utiliser les annotations avec Mockito ?
- Comment faire des assertions poussées sur les paramètres d'une méthode avec les ArgumentCaptor ?
- Qu'est-ce qu'un « spy » (espion) ?
- Comment simplifier l'injection de dépendances avec des mocks avec l'annotation @InjectMocks ?
Pour installer Mockito, il suffit de télécharger la dernière archive .jar (ou .zip si vous voulez également la Javadoc qui va avec) et d'inclure ce .jar dans votre classpath.
Pour les projets maven, il suffit d'ajouter cette dépendance dans votre fichier pom.xml et re-builder votre projet :
Code XML : | Sélectionner tout |
1 2 3 4 5 | <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>X.X.X</version> </dependency> |
Syntaxe générale :
Code Java : | Sélectionner tout |
1 2 | import static org.mockito.Mockito.*; ClasseAMocker objetMock = mock(ClasseAMocker.class) |
Exemple :
Dans les questions qui vont suivre, nous allons montrer des exemples de mocks qui serviront à tester unitairement les méthodes de la classe suivante, sans pour autant dépendre du comportement de ses dépendances :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | /** * Class programmeVoiture * La classe à tester unitairement * @author ok.Idriss */ public class ProgrammeVoiture(){ // Objet persistance qui sera lié par le principe d'injection de dépendances private IPersistanceModeleVoiture persistance; /** Méthodes à tester */ /** * Rechercher une liste de modèles en fonction de la marque * @param String marque * @return List<ModeleVoiture> tous les modèles en base appartenant à cette marque */ public List<ModeleVoiture> rechercherVoitureParMarque(String marque){ CritereRerchercheModeleVoiture citere = new CritereRerchercheModeleVoiture(); critere.setMarqueModele(marque); return persistance.searchModeleVoiture(critere); } /** * Rechercher un modèle de voiture via son id en base * @param Long id * @return ModeleVoiture résultat correspondant à la recherche */ public ModeleVoiture rechercherVoitureParId(Long id){ try { return persistance.searchModeleVoitureById(id); } catch (TooMuchResultException e){ System.out.println(« Trop de résultats avec le même id, revoyez la structure de votre table ! »); return null; } } /** * Enregistrer un modèle valorisé à partir d'un formulaire de création/modification * Doit mettre à jour en base le modèle ou l'ajouter dans le cas ou il n'existe pas * @param ModeleVoiture modele */ public boolean enregisterModeleVoiture(ModeleVoiture modele){ try{ if (null != modele.getId()){ persistance.updateModeleVoiture(modele); } else { persistance.addModeleVoiture(modele); } } catch (ErreurPersistance e){ System.out.println ("Erreur : " + e.getMessage); } } /** Getters et setters */ public IPersistanceModeleVoiture getPersistance() { return persistance; } public void setPersistance(IPersistanceModeleVoiture persistance) { this.persistance = persistance; } } |
Les méthodes à tester unitairement sont donc :
- rechercherVoitureParId()
- rechercherVoitureParMarque()
- enregisterModeleVoiture()
Pour aider à la compréhension de ce qui va suivre, voici :
1) Le contenu de la classe ModeleVoiture :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | /** * Objet persistant * @author ok.Idriss */ public class ModeleVoiture{ private Long id; private String libelle; private String marque; private Long nbKilometres; private Long age; /** Getters et setters */ public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getLibelle() { return libelle; } public void setLibelle(String libelle) { this.libelle = libelle; } public String getMarque() { return marque; } public void setMarque(String marque) { this.marque = marque; } public Long getNbKilometres() { return nbKilometres; } public void setNbKilometres(Long nbKilometres) { this.nbKilometres = nbKilometres; } public Long getAge() { return age; } public void setAge(Long age) { this.age = age; } } |
2) Le contenu de l'interface IPersistanceModeleVoiture (celle dont on va mocker le comportement pour s'abstraire de son implémentation) :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | /** * Interface IPersistanceModeleVoiture * Signatures des méthodes permettant l'interaction des objets à persister et la base de données * @author ok.Idriss */ public interface IPersistanceModeleVoiture { /** * Rechercher une liste de modèles de voiture en base de données à partir de critères * @param CritereRerchercheModeleVoiture critere de recherche * @return List<ModeleVoiture> liste de résultats correspondant à la recherche */ public List<ModeleVoiture> searchModeleVoiture(CritereRerchercheModeleVoiture critere); /** * Rechercher un modèle de voiture via son id en base * @param Long id * @return ModeleVoiture résultat correspondant à la recherche * @throws TooMuchResultException lorsque la recherche correspond à plusieurs résultats */ public ModeleVoiture searchModeleVoitureById(Long id) throws TooMuchResultException; /** * Persister une instance de ModeleVoiture en base de données * @param ModeleVoiture modele instance à persister en base * @return boolean true si l'insertion s'est bien passée sinon false * @throws ErreurPersistance en cas d'erreur */ public boolean addModeleVoiture(ModeleVoiture modele) throws ErreurPersistance; /** * Mettre à jour une instance de ModeleVoiture en base de données * @param ModeleVoiture modele instance à modifier en base * @return boolean true si la mise à jour s'est bien passée sinon false * @throws ErreurPersistance en cas d'erreur */ public boolean updateModeleVoiture(ModeleVoiture modele) throws ErreurPersistance; /** * Supprimer une instance de ModeleVoiture en base de données * @param ModeleVoiture modele instance à supprimer en base * @return boolean true si la suppression s'est bien passée sinon false * @throws ErreurPersistance en cas d'erreur */ public boolean deleteModeleVoiture(ModeleVoiture modele) throws ErreurPersistance; } |
3) Et enfin la classe CritereRerchercheModeleVoiture :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /** * Class CritereRerchercheModeleVoiture * Critères de recherche d'un modèle de voiture * @author ok.Idriss */ public class CritereRerchercheModeleVoiture{ private String libelleModele; private String marqueModele; /** Getters et setters */ public String getLibelleModele() { return libelleModele; } public void setLibelleModele(String libelleModele) { this.libelleModele = libelleModele; } public String getMarqueModele() { return marqueModele; } public void setMarqueModele(String marqueModele) { this.marqueModele = marqueModele; } } |
Et donc, pour commencer, voici comment déclarer le mock de la persistance au sein de notre TestCase :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import org.junit.Before; import static org.mockito.Mockito.*; /** * Class ProgrammeVoitureTest * Tests unitaires de la classe ProgrammeVoiture * @author ok.Idriss */ public class ProgrammeVoitureTest(){ private ProgrammeVoiture programme; private IPersistanceModeleVoiture persistanceMock; /** * Création du mock de la persistance et injection dans l'instance de la classe à tester * @throws Exception */ @Before public void setUp() throws Exception { programme = new ProgrammeVoiture(); // Création du mock persistanceMock = mock(IPersistanceModeleVoiture.class); // Injection du mock en lieu et place d'une réelle implémentation de IPersistanceModeleVoiture programme.setPersistance(persistanceMock); } } |
Syntaxe générale :
Code java : | Sélectionner tout |
1 2 3 4 5 6 | import static org.mockito.Mockito.*; import static org.mockito.Matchers.*; when(objetMock.methode(any(ClassArgument.class))).thenReturn(objetResultat); when(objetMock.methode(eq(valeurArgument))).thenReturn(objetResultat); when(objetMock.methode(valeurArgument)).thenReturn(objetResultat); |
Exemple :
Reprenons la classe de test "ProgrammeVoitureTest" de cette question et complétons-le :
Code java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; import static org.mockito.Mockito.*; import static org.mockito.Matchers.*; /** * Class ProgrammeVoitureTest * Tests unitaires de la classe ProgrammeVoiture * @author ok.Idriss */ public class ProgrammeVoitureTest(){ private ProgrammeVoiture programme; private IPersistanceModeleVoiture persistanceMock; /** Jeu de données */ private ModeleVoiture modeleTest; Long idExistant = 1L; Long idInexistant = 2L; String libelleTest = "Clio"; String marqueTest = "Renault"; List<ModeleVoiture> listTest; /** * Création du mock de la persistance et injection dans l'instance de la classe à tester * @throws Exception */ @Before public void setUp() throws Exception { programme = new ProgrammeVoiture(); // Création du mock persistanceMock = mock(IPersistanceModeleVoiture.class); // Injection du mock en lieu et place d'une réelle implémentation de IPersistanceModeleVoiture programme.setPersistance(persistanceMock); // Initialisation du jeu de données modeleTest = new ModeleVoiture(); modele.setMarque(marqueTest); modele.setLibelle(libelleTest); modele.setId(idExistant); listTest.add(modeleTest); } @Test public final void testRechercherVoitureParId(){ // Lorsque l'on appelera la méthode searchModeleVoitureById avec comme paramètre "1", le mock retournera modeleTest when(persistanceMock.searchModeleVoitureById(idExistant)).thenReturn(modeleTest); // l'id existe en base (tel qu'est défini le mock) // on vérifie qu'on renvoie bien le résultat retourné par la persistance ModeleVoiture result = programme.rechercherVoitureParId(idExistant); assertNotNull(result); assertEquals(idExistant, result.getId()); assertEquals(libelleTest, result.getLibelle()); assertEquals(marqueTest, result.getMarque()); // L'id n'existe pas en base // on vérifie que l'on renvoie bien null dans ce cas-là result = programme.rechercherVoitureParId(idInexistant); assertNull(result); } @Test public final void testRechercherVoitureParMarque(){ // Renverra toujours le même résultat // Le matcher any() contrairement au matcher eq() (utilisé implicitement dans le test du dessus) // permet de renvoyer le résultat quelque soit l'instance de la classe spécifiée en paramètre when(persistanceMock.searchModeleVoiture(any(CritereRerchercheModeleVoiture.class))).thenReturn(listTest); List<ModeleVoiture> lstResult = programme.rechercherVoitureParMarque("Renault"); assertNotNull(lstResult); assertFalse(lstResult.isEmpty()); // Ici aussi on aura malgré tout un résultat lstResult = programme.rechercherVoitureParMarque("Peugeot"); assertNotNull(lstResult); assertFalse(lstResult.isEmpty()); } } |
Syntaxe générale :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 | import static org.mockito.Mockito.*; import static org.mockito.Matchers.*; verify(objetMock).methode(valeurArgument); verify(objetMock).methode(eq(valeurArgument)); verify(objetMock).methode(any(ClassArgument.class)); |
Exemple :
Reprenons la classe de test "ProgrammeVoitureTest" de cette question et complétons-la :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | import org.junit.Before; import org.junit.Test; import static org.mockito.Mockito.*; /** * Class ProgrammeVoitureTest * Tests unitaires de la classe ProgrammeVoiture * @author ok.Idriss */ public class ProgrammeVoitureTest(){ private ProgrammeVoiture programme; private IPersistanceModeleVoiture persistanceMock; /** * Création du mock de la persistance et injection dans l'instance de la classe à tester * @throws Exception */ @Before public void setUp() throws Exception { programme = new ProgrammeVoiture(); // Création du mock persistanceMock = mock(IPersistanceModeleVoiture.class); // Injection du mock en lieu et place d'une réelle implémentation de IPersistanceModeleVoiture programme.setPersistance(persistanceMock); } @Test public final void testEnregisterModeleVoiture_Creation(){ // Instance sans id ModeleVoiture modele = new ModeleVoiture(); modele.setLibelle("libelle test"); programme.enregisterModeleVoiture(modele); // assertion => on a bien appelé la méthode addModeleVoiture avec comme paramètre modele verify(persistanceMock).addModeleVoiture(modele); } @Test public final void testEnregisterModeleVoiture_Modification(){ // Instance avec id ModeleVoiture modele = new ModeleVoiture(); modele.setLibelle("libelle test"); modele.setId(1L); programme.enregisterModeleVoiture(modele); // assertion => on a bien appelé la méthode updateModeleVoiture avec comme paramètre modele verify(persistanceMock).updateModeleVoiture(modele); } } |
Il est possible d'instancier directement les objets de Mockito tels que les mocks ou les ArgumentCaptor à l'aide d'annotations en utilisant le runner MockitoJUnitRunner de la façon suivante :
Code java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | @RunWith(MockitoJUnitRunner.class) public class MaClasseDeTest{ @Mock ObjetMock mock; @Spy ObjetSpy spy; @Captor ArgumentCaptor<ArgumentAVerifier> captor; } |
Ceci remplacerait les instructions suivantes :
Code java : | Sélectionner tout |
1 2 3 | ObjetMock mock = mock(ObjetMock.class); ObjetSpy = spy(ObjetSpy.class); ArgumentCaptor<ArgumentAVerifier> captor = ArgumentCaptor.forClass(ArgumentAVerifier.class); |
À noter qu'on peut remplacer le runner (notamment si on utilise déjà un autre runner junit) par l'instruction suivante dans une méthode annotée par @Before :
Code java : | Sélectionner tout |
MockitoAnnotations.initMocks(this);
Syntaxe générale :
Code java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | import org.mockito.ArgumentCaptor; import static org.mockito.Mockito.*; import static org.mockito.Matchers.*; ArgumentCaptor<ObjetParametreAVerifier> captor = ArgumentCaptor.forClass(ObjetParametreAVerifier.class); verify(ObjetMock).methodeAVerifier(eq(valeur), captor.capture()); ObjetParametreAVerifier objetAVerifier = captor.getValue(); // assertions sur les méthodes de objetAVerifier |
Exemple :
Reprenons la classe de test « ProgrammeVoitureTest » de cette question et complétons-la :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | import org.junit.Before; import org.junit.Test; import static org.mockito.Mockito.*; import static org.mockito.Matchers.*; import org.mockito.ArgumentCaptor; /** * Class ProgrammeVoitureTest * Tests unitaires de la classe ProgrammeVoiture * @author ok.Idriss */ public class ProgrammeVoitureTest(){ private ProgrammeVoiture programme; private IPersistanceModeleVoiture persistanceMock; /** * Création du mock de la persistance et injection dans l'instance de la classe à tester * @throws Exception */ @Before public void setUp() throws Exception { programme = new ProgrammeVoiture(); // Création du mock persistanceMock = mock(IPersistanceModeleVoiture.class); // Injection du mock en lieu et place d'une réelle implémentation de IPersistanceModeleVoiture programme.setPersistance(persistanceMock); } @Test public final void testEnregisterModeleVoiture_Creation(){ // Captor ArgumentCaptor<ModeleVoiture> captor = ArgumentCaptor.forClass(ModeleVoiture .class); // Instance sans id ModeleVoiture modele = new ModeleVoiture(); modele.setLibelle("libelle test"); programme.enregisterModeleVoiture(modele); // assertions verify(persistanceMock).addModeleVoiture(captor); assertEquals("libelle test", captor.getValue().getLibelle()); } @Test public final void testEnregisterModeleVoiture_Modification(){ // Captor ArgumentCaptor<ModeleVoiture> captor = ArgumentCaptor.forClass(ModeleVoiture .class); // Instance avec id ModeleVoiture modele = new ModeleVoiture(); modele.setLibelle("libelle test"); modele.setId(1L); programme.enregisterModeleVoiture(modele); // assertions verify(persistanceMock).updateModeleVoiture(captor); assertEquals("libelle test", captor.getValue().getLibelle()); } } |
Pour créer un captor sur un paramètre de type List<?>, il faut privilégier l'utilisation des annotations :
Code java : | Sélectionner tout |
1 2 | @Captor ArgumentCaptor<List<String>> captor; |
Voir Comment utiliser les annotations avec Mockito ? pour en savoir plus.
À l'instar des mocks, on peut de la même façon prédire le résultat d'une méthode d'un spy et faire des assertions sur les appels des méthodes de l'objet « espionné ».
La différence majeure entre le spy et le mock est que le spy se comporte par défaut comme l'objet réel si on ne prédit pas son comportement tandis que le mock lui ne fait rien. On sort donc un peu du cadre des objets simulacres.
Pour déclarer un Spy :
Code java : | Sélectionner tout |
1 2 3 | import static org.mockito.Mockito.*; ObjetSpy spy = spy(ObjetSpy.class); |
Il est également possible de remplacer cette instruction par l'annotation @Spy.
Il suffit ensuite de prédire les méthodes pour lesquelles on souhaite modifier le comportement avec when et de faire des assertions avec verify à l'instar d'un mock.
Outre la méthode de passer par les setters de la classe qu'on veut tester comme montré dans les exemples précédents, il est possible d'utiliser l'annotation @InjectMocks de la façon suivante :
Code java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | @RunWith(MockitoJUnitRunner.class) public class MyControllerTest { @Mock MyService serviceMock; // Injection de dépendances : la classe MyController qui a un attribut de type « MyService » va être instanciée automatiquement avec comme instance de « MyService » le mock au-dessus @InjectMocks @Spy // on peut aussi déclarer le controller comme Spy pour faire des asserts dessus MyController controller; // ... } |
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.