Introduction
Dans ce billet, nous allons présenter notre atelier pratique dans lequel à travers un projet Java pédagogique nous montrons comment marier l’outil Mockito avec le framework de test unitaire TestNG. Le projet consiste à tester la classe Calculette constituée de quatre méthodes mathématiques qui sont l’addition, la soustraction, la multiplication et la division. Dans un premier temps, nous réalisons le test unitaire avec TestNG sans recours à Mockito. Dans un deuxième temps, la classe à tester Calculette va être substituée par une classe fictive, en supposant par exemple que nous n’avons pas accès à son code source, et c’est là où intervient l’outil Mockito pour faire semblant que la classe Calculette existe et va nous permettre ainsi de dérouler notre test sans pour autant accéder réellement aux méthodes de la classe Calculette.
Mise en pratique
Pour réaliser notre atelier, nous avons besoin de l’IDE Eclipse. Nous commençons par créer un projet Maven. On va aller après vers le dépôt central de Maven http://mvnrepository.com pour récupérer les dépendances pour notre projet qui sont à savoir TestNG et Mockito. Notre fichier pom.xml se présentera ainsi :
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.13.0</version>
<scope>test</scope>
</dependency>
</dependencies>
La classe Calculette.java
Notre projet contient une seule classe à tester. Il s’agit de la classe Calculette.java qui se présente comme suit :
package org.knafil.testng;
public class Calculette {
public double add(double n1, double n2) {
double c;
c= n1+n2;
return c;
}
public double soustraire(double n1, double n2) {
double c;
c = n1 - n2;
return c;
}
public double produit(double n1, double n2) {
double c;
c= n1 * n2;
return c;
}
public double diviser(double n1, double n2) {
double c;
c= n1 / n2;
return c;
}
}
package org.knafil.testng;
public class Calculette {
public double add(double n1, double n2) {
double c;
c= n1+n2;
return c;
}
public double soustraire(double n1, double n2) {
double c;
c = n1 - n2;
return c;
}
public double produit(double n1, double n2) {
double c;
c= n1 * n2;
return c;
}
public double diviser(double n1, double n2) {
double c;
c= n1 / n2;
return c;
}
}
Les classes de test pour la méthode 'add'
Tester sans Mockito
Nous commençons par produire la classe de test de Calculette en utilisant le framework TestNG. Nous allons tester uniquement l’opération d’addition de deux nombres doubles. La classe de test se présente alors comme suit :
package org.knafil.testng;
import org.testng.annotations.Test;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
public class CalculetteTestWithoutMock {
Calculette calc;
@BeforeTest
public void create() {
calc = new Calculette();
}
@Test
public void test() {
Assert.assertEquals(3.0, calc.add(1, 2));
}
}
Au niveau de ce test, nous avons instancié réellement la classe Calculette pour pouvoir passer le test. Ceci a été fait au niveau de l’annotation @BeforeTest qui consiste à préparer le test pour TestNG. Donc avant de commencer le test, nous allons tout d’abord initié l’objet calc en créant une instance de la classe Calculette.
package org.knafil.testng;
import org.testng.annotations.Test;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
public class CalculetteTestWithoutMock {
Calculette calc;
@BeforeTest
public void create() {
calc = new Calculette();
}
@Test
public void test() {
Assert.assertEquals(3.0, calc.add(1, 2));
}
}
Au niveau de ce test, nous avons instancié réellement la classe Calculette pour pouvoir passer le test. Ceci a été fait au niveau de l’annotation @BeforeTest qui consiste à préparer le test pour TestNG. Donc avant de commencer le test, nous allons tout d’abord initié l’objet calc en créant une instance de la classe Calculette.
Pour voir comment dérouler un test sous TestNG, veuillez bien accéder à ce billet.
Tester avec Mockito
Supposant maintenant que pour une raison donnée, nous n’avons pas accès au code source de la classe Calculette. Dans ce cas, nous allons contourner cette situation et faire en sorte de substituer la classe Calculette par une autre classe Calculette qui fait pratiquement la même chose, c’est à dire qu’elles auront la même signature. Notre deuxième classe de test avec Mockito cette fois-ci se présente comme suit :
package org.knafil.testng;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class CalculetteTestWithMock {
Calculette calc;
@BeforeClass
public void create(){
calc = mock(Calculette.class);
when(calc.add(1, 2)).thenReturn(3.0);
}
@Test
public void test() {
Assert.assertEquals(3.0, calc.add(1, 2));
}
}
Comme vous voyez en haut, la classe Calculette n’a pas réellement été instanciée. C’est uniquement une substitution via Mockito (calc = mock(Calculette.class)). Après on demande à Mockito que lorsque la méthode add est appelée pour les deux paramètres 1 et 2 (when (calc.add(1, 2))) alors il doit nous retourner 3.0 (thenReturn(3.0)). Cette étape est renseignée dans la rubrique @BeforeTest de TestNG. Ensuite nous procédons à lancer notre test unitaire de manière normale au niveau de la rubrique @Test.
package org.knafil.testng;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class CalculetteTestWithMock {
Calculette calc;
@BeforeClass
public void create(){
calc = mock(Calculette.class);
when(calc.add(1, 2)).thenReturn(3.0);
}
@Test
public void test() {
Assert.assertEquals(3.0, calc.add(1, 2));
}
}
Comme vous voyez en haut, la classe Calculette n’a pas réellement été instanciée. C’est uniquement une substitution via Mockito (calc = mock(Calculette.class)). Après on demande à Mockito que lorsque la méthode add est appelée pour les deux paramètres 1 et 2 (when (calc.add(1, 2))) alors il doit nous retourner 3.0 (thenReturn(3.0)). Cette étape est renseignée dans la rubrique @BeforeTest de TestNG. Ensuite nous procédons à lancer notre test unitaire de manière normale au niveau de la rubrique @Test.
Tester avec les annotations de Mockito
Dans ce paragraphe, nous allons modifier légèrement notre code de test ci haut pour faire appel aux annotations de Mockito. Notre nouvelle classe de test se présentera ainsi comme suit :
package org.knafil.testng;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import org.mockito.Mock;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class CalculetteTestWithAnnotMock {
@Mock
Calculette calc;
@BeforeClass
public void create(){
initMocks(this);
when(calc.add(1, 2)).thenReturn(3.0);
}
@Test
public void test() {
Assert.assertEquals(3.0, calc.add(1, 2));
}
}
Au niveau de ce test, nous allons mocker directement la classe Calculette par l’annotation @Mock, et ensuite nous allons procéder à l’initialisation du Mock en faisant appel à la méthode initMocks au niveau de la rubrique @BeforeTest.
package org.knafil.testng;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import org.mockito.Mock;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class CalculetteTestWithAnnotMock {
@Mock
Calculette calc;
@BeforeClass
public void create(){
initMocks(this);
when(calc.add(1, 2)).thenReturn(3.0);
}
@Test
public void test() {
Assert.assertEquals(3.0, calc.add(1, 2));
}
}
Au niveau de ce test, nous allons mocker directement la classe Calculette par l’annotation @Mock, et ensuite nous allons procéder à l’initialisation du Mock en faisant appel à la méthode initMocks au niveau de la rubrique @BeforeTest.
La classe de test pour la méthode 'produit'
package org.knafil.testng;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class CalculetteTestProduit {
Calculette calc;
@BeforeClass
public void create(){
calc= mock(Calculette.class);
when(calc.produit(anyInt(), eq(0))).thenReturn(0);
}
@Test
public void test() {
assertSame(calc.produit(1,0),0);
assertSame(calc.produit(3,0),0);
}
}
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class CalculetteTestProduit {
Calculette calc;
@BeforeClass
public void create(){
calc= mock(Calculette.class);
when(calc.produit(anyInt(), eq(0))).thenReturn(0);
}
@Test
public void test() {
assertSame(calc.produit(1,0),0);
assertSame(calc.produit(3,0),0);
}
}
Dans ce code, on renseigne à Mockito que la multiplication de n'importe quel nombre par zéro va donner zéro au niveau du résultat.
La classe de test pour la méthode 'division'
Nous continuons notre atelier avec le test de la méthode ‘division’ de la classe Calculette qui va se présenter comme suit :
package org.knafil.testng;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class CalculetteTestAvecException {
Calculette calc;
@BeforeClass
public void create(){
calc = mock(Calculette.class);
when(calc.diviser(anyInt(), eq(0))).thenThrow(new ArithmeticException());
}
@Test(expected=ArithmeticException.class)
public void test() {
calc.diviser(1, 0);
}
}
package org.knafil.testng;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class CalculetteTestAvecException {
Calculette calc;
@BeforeClass
public void create(){
calc = mock(Calculette.class);
when(calc.diviser(anyInt(), eq(0))).thenThrow(new ArithmeticException());
}
@Test(expected=ArithmeticException.class)
public void test() {
calc.diviser(1, 0);
}
}
Dans ce code, on renseigne à Mockito que n'importe quelle division par 0 doit lever une exception :
when(calc.diviser(anyInt(), eq(0))).thenThrow(new ArithmeticException());
Commentaires
Enregistrer un commentaire