Exemple de test unitaire

Les articles précédents indiquaient ce qu’est Mockito, comment mocker une classe et comment définir des comportements sur les méthodes de la classe mockée :

Nous allons maintenant voir comment utiliser Mockito dans un test unitaire classique.

Code source de l’exemple

Cliquer sur le lien suivant pour récupérer le projet et changer l’extension du fichier en remplaçant « .key » par « .zip » :

Importer ce projet en tant que projet Maven dans eclipse et lancer le test « MeteoServiceTest ».

Présentation de la méthode à tester

Nous allons mocker les classes utilisées par la méthode à tester.

Nous prenons comme exemple le service de Meteo qui calcule, enregistre et retourne les températures des jours suivants aujourd’hui. Ce service utilise en dépendance la classe MeteoPrediction pour le calcul des températures sur les prochains jours et la classe MeteoDAO pour le lien avec la base de données.

Voici notre implémentation de la méthode « MeteoService.calculerTemperature() »:

public MeteoService {

  private MeteoPrediction meteoPrediction;
  private MeteoDAO meteoDAO;

  public List calculerTemperatures(int nbJours) {
    List temperatures = new ArrayList();
    for(int numJour=0; numJour<=nbJours; numJour++) {
      Integer temperature = meteoPrediction.calculer(numJour);
      meteoDAO.saveTemperature(numJour, temperature);
      temperatures.add(temperature);
    }
  }

  // getters/setters pour meteoPrediction et meteoDAO
  (...)

}

Mocker les classes auxiliaires de la classe à tester

Nous avons deux moyens de mocker les classes auxiliaires, soit via des lignes de codes, soit via des annotations.

Méthode 1 : via Mockito.mock :

public class MeteoServiceTest {

  private MeteoService meteoService;
  private MeteoPrediction meteoPrediction;
  private MeteoDAO meteoDAO;

  @Before
  public void setUp() {
    MeteoService meteoService = new MeteoService();
    meteoPrediction = Mockito.mock(MeteoPrediction.class);
    meteoService.setMeteoPrediction(meteoPrediction);
    meteoDAO = Mockito.mock(MeteoDAO.class);
    MeteoService.setMeteoDAO(meteoDAO);
  }

  @After
  public void tearDown() {
    meteoService = null;
    meteoPrediction = null;
    meteoDAO = null;
  }

}

Méthode 2 : via des annotations @InjectMocks et @Mock

@RunWith(MockitoJUnitRunner.class)
public class MeteoServiceTest {

  @InjectMocks
  private MeteoService meteoService;
  @Mock
  private MeteoPrediction meteoPrediction;
  @Mock
  private MeteoDAO meteoDAO;

}

Nous avons mocké les classes auxiliaires de la classe à tester.

Définir et utiliser les comportements sur les classes auxiliaires

Le fait d’avoir mocké les classes auxiliaires va nous permettre de définir des comportements sur leurs méthodes.

Pour rappel, voici le contenu de la méthode à tester :

public List calculerTemperatures(int nbJours) {
  List temperatures = new ArrayList();
  for(int numJour=0; numJour<=nbJours; numJour++) {
    Integer temperature = meteoPrediction.calculer(numJour);
    meteoDAO.saveTemperature(numJour, temperature);
    temperatures.add(temperature);
  }
}

Le test consiste à calculer, sauvegarder et récupérer les températures pour les trois prochains jours. Nous appelons donc la méthode à tester « MeteoService.calculerTemperatures(3) ».

Nous aurons donc 4 appels à « meteoPrediction.calculer » pour chaque jour de 0 à 3, de même pour « meteoDAO.saveTemperature » et quatre ajouts de température dans la liste retournée par la méthode à tester.

Nous avons comme températures pour les prochains jours :

  • aujourd’hui (jour J): 10°C
  • jour J+1: 8°C
  • jour J+2: 9°C
  • jour J+3: 11°C

D’apres ce qui a été expliqué dans l’article précédent, nous allons définir des comportements sur les méthodes des classes auxiliaires ou vérifier qu’elles ont été appelées.

« meteoPrediction.calculer » retourne une valeur en fonction du paramètre, voici un exemple de syntaxe à utiliser pour indiquer qu’elle retourne la température « 9 » pour le jour J+2 :

Mockito.when(meteoPrediction.calculer(2)).thenReturn(9);

De même pour les autres jours, au final nous aurons :

Mockito.when(meteoPrediction.calculer(0)).thenReturn(10);
Mockito.when(meteoPrediction.calculer(1)).thenReturn(8);
Mockito.when(meteoPrediction.calculer(2)).thenReturn(9);
Mockito.when(meteoPrediction.calculer(3)).thenReturn(11);

« meteoDAO.saveTemperature » ne retourne pas de valeur, c’est pourquoi nous n’effectuons qu’une vérification que cette méthode a bien été appelée pour chacune des 4 températures. Voici la syntaxe à utiliser :

Mockito.verify(meteoDAO).saveTemperature(0, 10);
Mockito.verify(meteoDAO).saveTemperature(1, 8);
Mockito.verify(meteoDAO).saveTemperature(2, 9);
Mockito.verify(meteoDAO).saveTemperature(3, 11);

Enfin, nous avons également que la méthode du service « MeteoService.calculerTemperatures(3) » que nous testons nous retourne bien une liste avec les 4 températures. Pour cela, nous n’avons qu’à vérifier que la liste contient les températures :

// Test
List temperatures = meteoService.calculerTemperature(3);

Assert.assertEquals(10, temperatures.get(0);
Assert.assertEquals(8, temperatures.get(1);
Assert.assertEquals(9, temperatures.get(2);
Assert.assertEquals(11, temperatures.get(3);

Nous venons de voir comment tester chaque ligne de la méthode du service « MeteoService.calculerTemperatures ».

Exemple complet

Voici pour rappel la méthode du service à tester :

public MeteoService {

  private MeteoPrediction meteoPrediction;
  private MeteoDAO meteoDAO;

  public List calculerTemperatures(int nbJours) {
    List temperatures = new ArrayList();
    for(int numJour=0; numJour<=nbJours; numJour++) {
      Integer temperature = meteoPrediction.calculer(numJour);
      meteoDAO.saveTemperature(numJour, temperature);
      temperatures.add(temperature);
    }
  }

  // getters/setters pour meteoPrediction et meteoDAO
  (...)

}

Voici le test complet pour tester cette méthode :

@RunWith(MockitoJUnitRunner.class)
public class MeteoServiceTest {

  @InjectMocks
  private MeteoService meteoService;
  @Mock
  private MeteoPrediction meteoPrediction;
  @Mock
  private MeteoDAO meteoDAO;

  @Test
  public void calculer_les_temperatures_sur_trois_jours() {
    // Given
    Mockito.when(meteoPrediction.calculer(0)).thenReturn(10);
    Mockito.when(meteoPrediction.calculer(1)).thenReturn(8);
    Mockito.when(meteoPrediction.calculer(2)).thenReturn(9);
    Mockito.when(meteoPrediction.calculer(3)).thenReturn(11);

    // When
    List temperatures = meteoService.calculerTemperatures(3);

    // Then
    Assert.assertEquals(10, temperatures.get(0);
    Assert.assertEquals(8, temperatures.get(1);
    Assert.assertEquals(9, temperatures.get(2);
    Assert.assertEquals(11, temperatures.get(3);

    Mockito.verify(meteoDAO).saveTemperature(0, 10);
    Mockito.verify(meteoDAO).saveTemperature(1, 8);
    Mockito.verify(meteoDAO).saveTemperature(2, 9);
    Mockito.verify(meteoDAO).saveTemperature(3, 11);
  }

}

Code source de l’exemple

Cliquer sur le lien suivant pour récupérer le projet et changer l’extension du fichier en remplaçant « .key » par « .zip » :

Importer ce projet en tant que projet Maven dans eclipse et lancer le test « MeteoServiceTest ».

Tagged with:
Publié dans Mockito, Test

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 :