public List<Message> lireMessages(String identifiant,
 String motDePasse)
 throws IdentificationException {
 boolean identification = identification.identifier(identifiant, motDePasse);
 if (identification) {
 // code qui retourne la liste des messages pour cet utilisateur
 } else {
 throw new IdentificationException();
Soucieux de la qualité de votre implémentation, vous vous lancez dans la création d'un test unitaire sous JUnit. Il devrait, au moins en partie, ressembler à la classe suivante :
/** Test de la classe MessagerieUtilisateur */
public class MessagerieUtilisateurTest {
 @Test
 public void testLireMessages() {
 // problème : comment instancier messagerie, il nous manque un paramètre
 MessagerieUtilisateur messagerie = new MessagerieUtilisateur(???);
 try {
 messagerie.lireMessages("toto", "mdp");
 } catch (IdentificationException e) {
 fail();
 try {
 messagerie.lireMessages("toto", "mauvais_mot_de_passe");
 // une exception aurait due être levée
 fail();
 } catch (IdentificationException e) {
 assertTrue(true);
Nous voici devant le problème, le développeur chargé d'implémenter l'interface codice_1 dont vous avez besoin ne peut pas encore vous la fournir, il a d'autres tâches prioritaires. Vous allez devoir vous en passer. C'est à ce moment que vous allez créer un bouchon. Cette classe va se substituer à celle qui manque le temps du test.
/** doublure de la classe IdentificationUtilisateur
 * c'est un bouchon qui est utilisé dans MessagerieUtilisateurTest
public class IdentificationUtilisateurStub implements IdentificationUtilisateur {
 /** seul le compte "toto" avec le mot de passe "mdp" peut s'identifier */
 @Override
 boolean identifier(String identifiant, String motDePasse) {
 if ("toto".equals(identifiant) && "mdp".equals(motDePasse) {
 return true;
 return false;
Il ne reste plus qu'à écrire dans le test ligne 7
MessagerieUtilisateur messagerie = new MessagerieUtilisateur(new IdentificationUtilisateurStub());
Vous pouvez maintenant dérouler le test, sans plus attendre. Le bouchon a permis de résoudre le problème de dépendance non-satisfaite envers un composant qui n'est pas disponible.
Les simulacres (ou « mock objects »).
Contrairement aux bouchons, les simulacres ne sont pas écrits par le développeur mais générés par l'usage d'un outil dédié, qui permet de générer un simulacre à partir de la classe originale.
Le simulacre généré est d'un type similaire à la classe originale et peut donc la remplacer.
On peut ensuite, par programmation, définir comment la doublure doit réagir quand elle est manipulée par la classe testée.
Introduction à Mockito.
Mockito est une bibliothèque Java qui permet de créer des simulacres.
Reprenons l'exemple précédent. Cette fois, grâce à Mockito, nous n'aurons plus besoin d'écrire le bouchon que nous avons utilisé précédemment. Nous n'allons pas utiliser un bouchon mais un simulacre, créé juste au moment du test.
import static org.mockito.Mockito.*; // permet d'utiliser mock() et when()
/** Test de la classe MessagerieUtilisateur avec un simulacre */
public class MessagerieUtilisateurTest {
 @Test
 public void testLireMessages() {
 // mockIdentification sera notre simulacre, comme on peut le voir
 // c'est bien un objet qui implémente l'interface IdentificationUtilisateur
 IdentificationUtilisateur mockIdentification;
 // la méthode statique mock de la class Mockito permet de créer
 // le simulacre.
 mockIdentification = mock(IdentificationUtilisateur.class);
 // maintenant, il faut spécifier le comportement attendu par notre simulacre
 // pour que le test se déroule bien
 when(mockIdentification.lireMessages("toto", "mdp")).thenReturn(true);
 when(mockIdentification.lireMessages("toto", "mauvais_mot_de_passe")).thenReturn(false);
 // notre simulacre est prêt à être utilisé
 MessagerieUtilisateur messagerie = new MessagerieUtilisateur(mockIdentification);
 try {
 messagerie.lireMessages("toto", "mdp");
 } catch (IdentificationException e) {
 fail();
 try {
 messagerie.lireMessages("toto", "mauvais_mot_de_passe");
 // une exception aurait due être levée
 fail();
 } catch (IdentificationException e) {
 assertTrue(true);
L'outil de génération de simulacres nous a permis d'éviter d'écrire une nouvelle classe (le bouchon). Cela nous a permis d'écrire le test plus vite sans ajouter de code excessif.
Limites de Mockito.
Mockito, en interne, joue avec la réflexion et l'héritage de Java. Par conséquent, on ne peut pas "mocker"
Les trois dernières impossibilités sont dues à la façon dont Java charge les classes en mémoire. Il est possible de remédier à ces limitations justement en changeant la façon dont Java charge les classes. C'est ce que propose PowerMock qui étend Mockito.
Les espions (ou « spy »).
Un espion est une doublure qui enregistre les traitements qui lui sont fait. Les tests se déroulent alors ainsi :
L'intérêt de cette méthode est manifeste lorsqu'il s'agit de tester des méthodes privées. On ne peut vérifier la valeur retournée ou que les paramètres passés successivement au travers des différentes méthodes sont bons. Dans ce cas, on laisse l'espion passer successivement pour toutes les méthodes privées et c'est seulement à la fin que l'espion nous rapporte ce qu'il s'est vraiment passé.
Une classe espionne peut être codée à la main mais la plupart des outils de création de simulacres évoqués plus haut créent des doublures qui sont aussi des espions.
Un exemple, avec Mockito.
Les doublures créées par Mockito sont aussi des espions. Réécrivons notre test en utilisant cette possibilité.
/** Test de la classe MessagerieUtilisateur avec un espion */
public class MessagerieUtilisateurTest {
 public void testLireMessages() throws Exception {
 // mockIdentification sera notre simulacre, comme on peut le voir
 // c'est bien un objet qui implémente l'interface IdentificationUtilisateur
 IdentificationUtilisateur mockIdentification;
 // la méthode statique mock de la class Mockito permet de créer
 // le simulacre.
 mockIdentification = Mockito.mock(IdentificationUtilisateur.class);
 // maintenant, il faut spécifier le comportement attendu par notre simulacre
 // pour que le test se déroule bien
 Mockito.when(mockIdentification.identifier("toto", "mdp")).thenReturn(true);
 Mockito.when(mockIdentification.identifier("toto", "mauvais_mot_de_passe")).thenReturn(false);