Cours Java Jun It
Cours Java Jun It
Achref El Mouelhi
[Link]@[Link]
1 Introduction
2 Premier exemple
3 Assertions
4 Suppositions
5 Pre/Post test
6 Mockito
8 Capture d’arguments
10 JUnit et Maven
12 Recouvrement du code
JUnit
JUnit ?
Framework open-source pour Java créé par Kent Beck et Erich Gamma.
JUnit
JUnit ?
Framework open-source pour Java créé par Kent Beck et Erich Gamma.
JUnit
H I ©
Contenant quelques méthodes de test (annotées par @Test)
UEL
O
Permettant de tester le bon fonctionnement d’une classe (en
testant ses méthodes)
f E LM
ch r e
©A
Remarque
JUnit
Étape
JUnit
©A
if (y == 0)
throw new ArithmeticException();
return x / y;
}
}
JUnit
Pour créer une classe de test
©A
Chercher calcul, sélectionner Calcul - [Link] et valider
Cliquer sur Finish puis sur ok (pour valider Add JUnit 5 library to the
build path dans Perform the following action:)
Le code généré :
package [Link];
import [Link];
class CalculTest {
@BeforeAll
H I ©
EL
static void setUpBeforeClass() throws Exception { }
@AfterAll
O U
static void tearDownAfterClass() throws Exception { }
@BeforeEach
void setUp() throws Exception {
f E} LM
@AfterEach
ch r e
void tearDown() throws Exception { }
@Test
void testSomme() {©A
fail("Not yet implemented");
}
@Test
void testDivision() {
fail("Not yet implemented");
}
}
JUnit
Nous parlerons de ces quatre méthodes dans une autre section
@BeforeAll
static void setUpBeforeClass() throws Exception {
}
H I ©
@AfterAll
UEL
O
static void tearDownAfterClass() throws Exception {
}
f E LM
@BeforeEach
ch r e
©A
void setUp() throws Exception {
}
@AfterEach
void tearDown() throws Exception {
}
JUnit
Pour tester
Faire un clic droit sur le la classe de test
H I ©
Aller dans Run As > JUnit Test
UEL
O
f E LM
ch r e
©A
JUnit
Pour tester
Faire un clic droit sur le la classe de test
H I ©
Aller dans Run As > JUnit Test
UEL
O
f E LM
ch r e
Résultat
©A
2 Exécutions : 2 Échecs : car les deux méthodes de test sont vides.
JUnit
Implémentons testSomme() en ciblant chaque fois les cas particuliers
void testSomme() {
Calcul calcul = new Calcul();
if ([Link](2, 3) != 5)
fail("faux pour deux entiers positifs");
if ([Link](-2, -3) != -5)
H I ©
fail("faux pour deux entiers négatifs");
UEL
O
LM
if ([Link](-2, 3) != 1)
if ([Link](0, 3) != 3)
r e E
fail("faux pour deux entiers de signe différent");
f
ch
©A
fail("faux pour x nul");
if ([Link](2, 0) != 2)
fail("faux pour y nul");
if ([Link](0, 0) != 0)
fail("faux pour x et y nuls");
}
JUnit
Implémentons testSomme() en ciblant chaque fois les cas particuliers
void testSomme() {
Calcul calcul = new Calcul();
if ([Link](2, 3) != 5)
fail("faux pour deux entiers positifs");
if ([Link](-2, -3) != -5)
H I ©
fail("faux pour deux entiers négatifs");
UEL
O
LM
if ([Link](-2, 3) != 1)
if ([Link](0, 3) != 3)
r e E
fail("faux pour deux entiers de signe différent");
f
ch
©A
fail("faux pour x nul");
if ([Link](2, 0) != 2)
fail("faux pour y nul");
if ([Link](0, 0) != 0)
fail("faux pour x et y nuls");
}
JUnit
Remarques
Pour tester une méthode, on peut aussi utiliser les assertions ou les
assmptions.
H I ©
UEL
O
f E LM
ch r e
©A
JUnit
Remarques
Pour tester une méthode, on peut aussi utiliser les assertions ou les
assmptions.
H I ©
U EL
O
Assertions
f E LM
r e
ch définies dans la classe Assertions.
Méthodes statiques
© A
Permettant de vérifier le bon déroulement d’un test : si la
vérification échoue, l’assertion lève une exception et le test
échoue.
Acceptant depuis la version 5 les expressions Lambda.
Quelques assertions
I ©
assertEquals(valeur attendue, appel de méthode, message) : permet de
H
EL
vérifier l’égalité de valeur (sa réciproque est assertNotEquals).
O U
assertSame(objet attendu, objet retourné, message) : permet de vérifier si
assertNotSame).
f E LM
objet attendu et objet retourné réfèrent le même objet (sa réciproque est
ch r e
assertArrayEquals(tableau attendu, tableau retourné, message) :
©A
permet de vérifier l’égalité de deux tableaux.
...
JUnit
Remarques
H I ©
EL
En l’absence d’un message explicite, un message d’erreur par
défaut sera affiché.
M OU
f
Les méthodes assertX()E L aussi avoir la signature
peuvent
c hr e
suivante : assertX(message, valeurAttendue,
© A
appelDeMéthodeATester)
void testDivision() {
Calcul calcul = new Calcul();
assertFalse([Link](6, 3) == 0, "2 entiers positifs");
assertEquals(2, [Link](-6, -3), "2 entiers négatifs");
assertNotNull([Link](-6, 3), "2 entiers de signe diff");
assertTrue([Link](0, 3) == 0, "entier x nul");
Throwable e = null;
try {
H I ©
EL
[Link](2, 0);
}
O U
LM
catch (Throwable ex) {
e = ex;
}
r e f E
ch
assertTrue(e instanceof ArithmeticException);
©A
e = null;
try {
[Link](0, 0);
}
catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof ArithmeticException);
}
JUnit
f E LM
in Console View, en face Failure Trace pour visualiser les
r e
détails de l’erreur dans la console).
ch
©A
Dans ce cas, il faut localiser l’erreur, la corriger et relancer.
void testDivision() {
Calcul calcul = new Calcul();
assertFalse([Link](6, 3) == 2, "2 entiers positifs");
assertEquals(1, [Link](-6, -3), "2 entiers négatifs");
assertNotNull([Link](-6, 3), "2 entiers de signe diff");
assertTrue([Link](0, 3) == 0, "entier x nul");
Throwable e = null;
try {
H I ©
EL
[Link](2, 0);
}
O U
LM
catch (Throwable ex) {
e = ex;
}
r e f E
ch
assertTrue(e instanceof ArithmeticException);
©A
e = null;
try {
[Link](0, 0);
}
catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof ArithmeticException);
}
JUnit
Constats
H I ©
Deux assertions incorrectes mais une seule exception retournée.
UEL
O
f E LM
ch r e
©A
JUnit
Constats
H I ©
Deux assertions incorrectes mais une seule exception retournée.
UEL
O
f E LM
Solution ch r e
©A
Regrouper les assertions avec assertAll
JUnit
void testDivision() {
Calcul calcul = new Calcul();
assertAll("premier regroupement",
() -> assertFalse([Link](6, 3) == 2, "2 entiers positifs"),
I ©
() -> assertEquals(1, [Link](-6, -3), "2 entiers négatifs"),
H
() -> assertNotNull([Link](-6, 3), "2 entiers de signe diff"),
EL
() -> assertTrue([Link](0, 3) == 0, "entier x nul")
);
Throwable e = null;
O U
LM
try {
[Link](2, 0);
} catch (Throwable ex) {
e = ex;
r e f E
}
ch
©A
assertTrue(e instanceof ArithmeticException);
e = null;
try {
[Link](0, 0);
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof ArithmeticException);
}
JUnit
En lançant les tests précédents, les deux échecs sont signalés ainsi que le nom du
regroupement
H I ©
U EL
[Link]: premier regroupement (2 failures)
O
LM
[Link]: 2 entiers positifs ==>
expected: <false> but was: <true>
f E
[Link]: 2 entiers négatifs ==>
r e
ch
expected: <1> but was: <2>
©A
JUnit
Assumptions (suppositions)
H I ©
U
Méthodes statiques définies dans la classe L
EAssumptions.
L
Permettant de conditionner l’ex MO d’un bloc de test : si
écution
r e f E échoue, le test sera désactivé sans
l’évaluation de l’assumption
être échoué.Ach
©
Modifions testDivision() pour que l’ensemble de tests précédents ne soit exécuté que
si on travaille dans un environnement Windows
void testDivision() {
Calcul calcul = new Calcul();
assumeTrue([Link]("OS").startsWith("Windows"));
assertFalse([Link](6, 3) == 0, "2 entiers positifs");
assertEquals(2, [Link](-6, -3), "2 entiers négatifs");
assertNotNull([Link](-6, 3), "2 entiers de signe diff");
assertTrue([Link](0, 3) == 0, "entier x nul");
H I ©
EL
Throwable e = null;
try {
O U
LM
[Link](2, 0);
} catch (Throwable ex) {
e = ex;
r e f E
ch
}
©A
assertTrue(e instanceof ArithmeticException);
e = null;
try {
[Link](0, 0);
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof ArithmeticException);
}
void testDivision() {
Calcul calcul = new Calcul();
assumingThat([Link]("OS").startsWith("Windows"), () -> {
assertFalse([Link](6, 3) == 0, "2 entiers positifs");
assertEquals(2, [Link](-6, -3), "2 entiers négatifs");
assertNotNull([Link](-6, 3), "2 entiers de signe diff");
assertTrue([Link](0, 3) == 0, "entier x nul");
Throwable e = null;
H I ©
EL
try {
[Link](2, 0);
O U
LM
} catch (Throwable ex) {
e = ex;
}
r e f E
ch
assertTrue(e instanceof ArithmeticException);
©A
e = null;
try {
[Link](0, 0);
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof ArithmeticException);
});
}
JUnit
Quelques assumptions
assumeTrue()
H I ©
assumeFalse()
UEL
O
assumeThat()
f E LM
assumingThat()
ch r e
©A
assumeNoException()
assumeNotNull() :
JUnit
ch r e
©A
JUnit
ch r e
©A
Solution
On peut utiliser les méthodes setUp() et tearDown() qui sont respectivement exécutées
avant et après l’appel de chaque méthode de test.
@BeforeAll
static void setUpBeforeClass() throws Exception {
[Link]("BeforeAll");
}
@AfterAll
static void tearDownAfterClass() throws Exception {
H I ©
[Link]("AfterAll");
UEL
}
O
f E LM
@BeforeEach
ch r
void setUp() throws Exception { e
} ©A
[Link]("BeforeEach");
@AfterEach
void tearDown() throws Exception {
[Link]("AfterEach");
}
JUnit
H I ©
UEL
O
f E LM
ch r e
©A
JUnit
H I ©
UEL
O
Le résultat
f E LM
BeforeAll
ch r e
BeforeEach
AfterEach
©A
BeforeEach
AfterEach
AfterAll
JUnit
JUnit
Remarques
H I ©
@BeforeAll était @BeforeClass dans JUnit 4.
UEL
O
f E LM
@AfterAll était @AfterClass dans JUnit 4.
r e
@BeforeEach était @Before dans JUnit 4.
ch
©A
@AfterEach était @After dans JUnit 4.
JUnit
Mock ?
Doublure, objet factice (fake object)
H I ©
permettant de reproduire le comportement d’un objet réel non
implémenté
UEL
O
f E LM
ch r e
©A
JUnit
Mock ?
Doublure, objet factice (fake object)
H I ©
permettant de reproduire le comportement d’un objet réel non
implémenté
UEL
O
f E LM
ch r e
Mockito ?
© A
Framework open-source pour Java
Générateur automatique de doublures
Un seul type de Mock possible et une seule façon de le créer
JUnit
c r e
utilise la méthodehcarre() de cette interface CalculService
© A
JUnit
L’interface CalculService
package [Link];
H I ©
UEL
public interface CalculService { O
f E LM
public int carre(int x);
ch r e
} ©A
JUnit
La classe Calcul
package [Link];
©A
}
JUnit
Pour tester la classe Calcul dans TestCalcul, il faut commencer par
instancier CalculService
class CalculTest {
Calcul calcul;
CalculService calculService;
H I ©
@BeforeEach
UEL
O
LM
void setUp() throws Exception {
f E
calcul = new Calcul(calculService);
r e
ch
}
@Test ©A
void testSommeCarre() {
assertTrue([Link](2, 3) == 13, "calcul
exact");
}
// + le code precedent
JUnit
[Link]
at [Link]([Link])
H I ©
at [Link]([Link])
UEL
O
f E LM
ch r e
©A
JUnit
[Link]
at [Link]([Link])
at [Link]([Link])
H I ©
UEL
O
Explication
f E LM
ch r e
©A
La source de l’erreur est l’appel de la méthode carre(x) qui n’est pas implémenté.
STUB (les bouchons en français) : code qui renvoie le même résultat pour une méthode
invoquée.
JUnit
Pour tester la classe Calcul dans TestCalcul, il faut commencer par
instancier un objet d’une classe anonyme implémentant CalculService
class CalculTest {
Calcul calcul;
H I ©
CalculService calculService =
EL
new CalculService() {
U
O
LM
@Override
public int carre(int x) {
r e f E
// TODO Auto-generated method stub
ch
©A
return x * x;
}
};
// + le code précédent
JUnit
O U
f E LM
CalculService calculService = (int x) -> x * x;
h r e
// + le code cprécédent
© A
}
JUnit
En testant
tout se passe bien et le test est passé. H I ©
UEL
O
f E LM
ch r e
©A
JUnit
En testant
tout se passe bien et le test est passé. H I ©
UEL
O
f E LM
On peut utiliser les mocks ch r e
©A
pour créer un objet factice de CalculService.
JUnit
Démarche
Aller dans
H I ©
EL
[Link] et
télécharger mockito-core
M OU
laL
Créer un répertoire lib àE racine du projet
e f
hr mockito-core et copier les 4 .jar
Décompresserc
dans lib© A l’archive
JUnit
H I ©
EL
import static [Link].*;
O U
f E LM
ch r e
©A
JUnit
H I ©
EL
import static [Link].*;
O U
f E LM
ch r e
Remplaçons l’instanciation de CalculService par un mock
CalculService A
calculService = mock([Link]);
©
JUnit
Utilisons when ... thenReturn pour indiquer ce qu’il faut retourner lorsque
la méthode carre est appelée avec les paramètres 2 ou 3
@Test
H I ©
void testSommeCarre() {
when([Link](2)).thenReturn(4);
U EL
O
LM
when([Link](3)).thenReturn(9);
}
r e E
assertTrue([Link](2, 3) == 13, "calcul exact");
f
ch
©A
JUnit
Utilisons when ... thenReturn pour indiquer ce qu’il faut retourner lorsque
la méthode carre est appelée avec les paramètres 2 ou 3
@Test
H I ©
void testSommeCarre() {
when([Link](2)).thenReturn(4);
U EL
O
LM
when([Link](3)).thenReturn(9);
}
r e E
assertTrue([Link](2, 3) == 13, "calcul exact");
f
ch
©A
Lancez le test et vérifiez qu’il se termine correctement.
JUnit
@Test
void testSommeCarre() {
H I ©
when([Link](2)).thenReturn(4);
U EL
doReturn(9).when(calculService).carre(3);
O
}
f E LM
assertTrue([Link](2, 3) == 13, "calcul exact");
ch r e
©A
JUnit
@Test
void testSommeCarre() {
H I ©
when([Link](2)).thenReturn(4);
U EL
doReturn(9).when(calculService).carre(3);
O
}
f E LM
assertTrue([Link](2, 3) == 13, "calcul exact");
ch r e
©A
Lancez le test et vérifiez qu’il se termine correctement.
JUnit
Remarques
H I ©
EL
OU
when ... thenReturn n’accepte pas les méthodes void.
M
doReturn accepte toutesE
f Lméthodes quelle que soit la valeur
les
de retour.
chr e
© A
JUnit
Pour vérifier que le mock a bien été appelé, on peut utiliser la méthode verify
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
when([Link](3)).thenReturn(9);
H I ©
EL
when([Link](4)).thenReturn(16);
assertTrue([Link](2, 3) == 13, "calcul exact");
O U
LM
verify(calculService).carre(2);
}
r e f E
ch
©A
JUnit
Pour vérifier que le mock a bien été appelé, on peut utiliser la méthode verify
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
when([Link](3)).thenReturn(9);
H I ©
EL
when([Link](4)).thenReturn(16);
assertTrue([Link](2, 3) == 13, "calcul exact");
O U
LM
verify(calculService).carre(2);
}
r e f E
ch
©A
Remarque
JUnit
JUnit
JUnit
Le résultat est
Wanted but not invoked:
[Link](2);
H I ©
EL
-> at [Link](
[Link])
O U
LM
Actually, there were zero interactions with this mock.
r e f E
ch
©A
JUnit
Le résultat est
Wanted but not invoked:
[Link](2);
H I ©
EL
-> at [Link](
[Link])
O U
LM
Actually, there were zero interactions with this mock.
r e f E
ch
Explication ©A
Tout mock créé doit être invoqué.
JUnit
Pour vérifier que carre(2) a été appelé une seule fois, on peut utiliser la
méthode times
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
H I ©
when([Link](3)).thenReturn(9);
UEL
O
assertTrue([Link](2, 3) == 13, "calcul exact");
}
verify(calculService, times(1)).carre(2);
f E LM
ch r e
©A
JUnit
Pour vérifier que carre(2) a été appelé une seule fois, on peut utiliser la
méthode times
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
H I ©
when([Link](3)).thenReturn(9);
UEL
O
assertTrue([Link](2, 3) == 13, "calcul exact");
}
verify(calculService, times(1)).carre(2);
f E LM
ch r e
©A
Remarque
JUnit
Pour vérifier que carre(2) a été appelé au moins une fois, on peut utiliser la
méthode atLeast
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
H I ©
when([Link](3)).thenReturn(9);
UEL
O
assertTrue([Link](2, 3) == 13, "calcul exact");
}
verify(calculService, atLeast(1)).carre(2);
f E LM
ch r e
©A
JUnit
Pour vérifier que carre(2) a été appelé au moins une fois, on peut utiliser la
méthode atLeast
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
H I ©
when([Link](3)).thenReturn(9);
UEL
O
assertTrue([Link](2, 3) == 13, "calcul exact");
}
verify(calculService, atLeast(1)).carre(2);
f E LM
ch r e
©A
Remarque
JUnit
H I ©
atLeastOnce() : au moins une fois .
UEL
O
LM
atMost(n) : au plus n fois.
r e
atMostOnce() : au plus une fois.f E
ch
...
©A
JUnit
Pour vérifier que carre a été appelé deux fois avec des paramètres de type
Integer, on peut utiliser la méthode any
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
when([Link](3)).thenReturn(9);
H I ©
when([Link](4)).thenReturn(16);
UEL
O
assertTrue([Link](2, 3) == 13, "calcul exact");
class));
f E LM
verify(calculService, times(2)).carre([Link](Integer.
}
ch r e
©A
JUnit
Pour vérifier que carre a été appelé deux fois avec des paramètres de type
Integer, on peut utiliser la méthode any
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
when([Link](3)).thenReturn(9);
H I ©
when([Link](4)).thenReturn(16);
UEL
O
assertTrue([Link](2, 3) == 13, "calcul exact");
class));
f E LM
verify(calculService, times(2)).carre([Link](Integer.
}
ch r e
©A
Remarque
JUnit
Pour vérifier que carre a été appelé deux fois avec des paramètres de type
Integer, on peut aussi utiliser la méthode anyInt
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
H I ©
EL
when([Link](3)).thenReturn(9);
when([Link](4)).thenReturn(16);
O U
LM
assertTrue([Link](2, 3) == 13, "calcul exact");
}
r e E
verify(calculService, times(2)).carre([Link]());
f
ch
©A
JUnit
Pour vérifier que carre a été appelé deux fois avec des paramètres de type
Integer, on peut aussi utiliser la méthode anyInt
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
H I ©
EL
when([Link](3)).thenReturn(9);
when([Link](4)).thenReturn(16);
O U
LM
assertTrue([Link](2, 3) == 13, "calcul exact");
}
r e E
verify(calculService, times(2)).carre([Link]());
f
ch
©A
Remarque
JUnit
JUnit
Pour vérifier que carre(4) n’a jamais été appelé, on peut utiliser la méthode
never
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
H I ©
EL
when([Link](3)).thenReturn(9);
assertTrue([Link](2, 3) == 13, "calcul exact");
O U
LM
verify(calculService, never()).carre(4);
}
r e f E
ch
©A
JUnit
Pour vérifier que carre(4) n’a jamais été appelé, on peut utiliser la méthode
never
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
H I ©
EL
when([Link](3)).thenReturn(9);
assertTrue([Link](2, 3) == 13, "calcul exact");
O U
LM
verify(calculService, never()).carre(4);
}
r e f E
ch
©A
Remarque
JUnit
Pour vérifier si carre() a été appelé une seule fois quel que soit le nombre de
paramètres, on peut utiliser la méthode only
H I ©
EL
@Test
void testSommeCarre() {
O U
LM
when([Link](2)).thenReturn(4);
r e E
when([Link](3)).thenReturn(9);
f
assertTrue([Link](2, 3) == 13, "calcul exact");
ch
©A
verify(calculService, only()).carre(4);
}
JUnit
Pour vérifier l’ordre d’interactions avec le mock, on peut utiliser la méthode inOrder
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
when([Link](3)).thenReturn(9);
assertTrue([Link](2, 3) == 13, "calcul exact");
H I ©
InOrder ordre = [Link](calculService);
[Link](calculService).carre(2);
UEL
O
LM
[Link](calculService).carre(3);
}
r e f E
ch
©A
JUnit
Pour vérifier l’ordre d’interactions avec le mock, on peut utiliser la méthode inOrder
@Test
void testSommeCarre() {
when([Link](2)).thenReturn(4);
when([Link](3)).thenReturn(9);
assertTrue([Link](2, 3) == 13, "calcul exact");
H I ©
InOrder ordre = [Link](calculService);
[Link](calculService).carre(2);
UEL
O
LM
[Link](calculService).carre(3);
}
r e f E
ch
©A
Remarque
JUnit
@Test
void testSommeCarre() {
when([Link]([Link]())).thenAnswer(
H I ©
(invocation) -> {
U EL
Integer entier = [Link](0);
O
LM
return entier * entier;
});
r e f E
assertTrue([Link](2, 3) == 13, "calcul exact");
}
ch
©A
JUnit
@Test
void testSommeCarre() {
when([Link]([Link]())).thenAnswer(
H I ©
(invocation) -> {
U EL
Integer entier = [Link](0);
O
LM
return entier * entier;
});
r e f E
assertTrue([Link](2, 3) == 13, "calcul exact");
}
ch
©A
Lancez le test et vérifiez qu’il se termine correctement.
JUnit
@Test
void testSommeCarre() {
doAnswer((invocation) -> {
H I ©
Integer entier = [Link](0);
U EL
return entier * entier;
O
}).when(calculService).carre([Link]());
f E LM
}
ch r e
assertTrue([Link](2, 3) == 13, "calcul exact");
©A
JUnit
@Test
void testSommeCarre() {
doAnswer((invocation) -> {
H I ©
Integer entier = [Link](0);
U EL
return entier * entier;
O
}).when(calculService).carre([Link]());
f E LM
}
ch r e
assertTrue([Link](2, 3) == 13, "calcul exact");
©A
Lancez le test et vérifiez qu’il se termine correctement.
JUnit
Remarques
H I ©
EL
OU
when ... thenAnswer n’accepte pas les méthodes void.
M
doAnswer accepte toutesE
f Lméthodes quelle que soit la valeur
les
de retour.
chr e
© A
JUnit
Remarques
H I ©
Un mock est initialement introduit pour simuler des objets U EL
O
f E LM
externes ou non instanciables (interface, classe abstraite...)
ch r e
Mais il peut aussi simuler le comportement d’une classe concrète.
©A
@RunWith([Link])
class PointTest {
Point pointMock = [Link]([Link]);
@BeforeAll
static void setUpBeforeClass() throws Exception {
}
@AfterAll
©
static void tearDownAfterClass() throws Exception {
}
H I
@BeforeEach
void setUp() throws Exception {
U EL
}
O
@AfterEach
f E LM
}
ch r e
void tearDown() throws Exception {
©A
@Test
void testDeplacerOrd() {
}
@Test
void testDeplacerAbs() {
}
@Test
void testDeplacer() {
}
}
JUnit
Utilisons when ... thenThrow pour lever une exception si certains paramètres sont
présents
@Test
void testDeplacerOrd() {
H I ©
when([Link](Double.MAX_VALUE))
U EL
O
LM
.thenThrow([Link]);
Throwable e = null;
try {
r e f E
ch
[Link](Double.MAX_VALUE);
©A
} catch (Exception ex) {
e = ex;
}
assertTrue(e instanceof ArithmeticException);
}
JUnit
Ajoutons l’affichage suivant dans la méthode deplacerOrd
}
return this;
H I ©
U EL
O
f E LM
ch r e
©A
JUnit
Ajoutons l’affichage suivant dans la méthode deplacerOrd
}
return this;
H I ©
U EL
O
f E LM
Remarques
ch r e
©A
En lançant le test, le message ajouté ne s’affiche pas.
Le mock renvoie null si la méthode appelée n’est pas définie avec un when.
JUnit
Remarques H I ©
U EL
O
when ... thenThrow n’accepte pas les méthodes void.
Mais on peut utiliser doThrow. f E LM
ch r e
©A
JUnit
Utilisons doThrow pour lever une exception si certains paramètres sont présents pour
tester la méthode déplacerAbs ne retournant pas de valeurs
@Test
void testDeplacerAbs() {
H I ©
doThrow([Link]).when(pointMock).deplacerAbs(
Double.MAX_VALUE);
U EL
O
LM
Throwable e = null;
try {
e f E
[Link](Double.MAX_VALUE);
r
} catch (Exception ex) {
ch
©A
e = ex;
}
assertTrue(e instanceof ArithmeticException);
}
JUnit
Remarques
f E LM
ch r e
©A
JUnit
Remarques
f E LM
ch r e
Solution
©A
Utiliser les espions (Spy).
JUnit
Spy ?
I
Un spy est un mock partiel créé à partir d’une instance réelle.
H ©
UEL
O
Une partie de l’objet sera simulée et une partie utilisera des
invocations de méthodes réelles.
f E LM
ch r e
Si un spy appelle une méthode non mentionnée dans un when,
©A
c’est la méthode originale définie dans la classe réelle qui sera
appelée.
JUnit
H I ©
UEL
O
f E LM
ch r e
©A
JUnit
H I ©
EL
OU
Par celle d’un spy construit à partir d’une instance réelle
M
f E L
Point pointMock = [Link](new Point(2, 2));
ch r e
© A
JUnit
H I ©
EL
OU
Par celle d’un spy construit à partir d’une instance réelle
M
f E L
Point pointMock = [Link](new Point(2, 2));
ch r e
© A
Vérifiez que les tests précédents passent toujours.
@Test
void testDeplacer() {
Point resultat = new Point(6.0, 6.0);
assertTrue([Link]([Link](4)));
}
H I ©
UEL
O
f E LM
ch r e
©A
@Test
void testDeplacer() {
Point resultat = new Point(6.0, 6.0);
assertTrue([Link]([Link](4)));
}
H I ©
UEL
Et redéfinissons la méthode equals dans Point
O
@Override
f E LM
public boolean equals(Object obj) {
Point p = (Point) obj;
ch r e
©A
return [Link] == abs && [Link] == ord;
}
@Test
void testDeplacer() {
Point resultat = new Point(6.0, 6.0);
assertTrue([Link]([Link](4)));
}
H I ©
UEL
Et redéfinissons la méthode equals dans Point
O
@Override
f E LM
public boolean equals(Object obj) {
Point p = (Point) obj;
ch r e
©A
return [Link] == abs && [Link] == ord;
}
JUnit
Remarques
Pour les spy, when ... thenReturn et when ... H I ©
UEL
thenThrow appellent la méthode de la classe réelle juste avant
O
f E LM
que la valeur spécifiée ne soit renvoyée. Donc, si la méthode
appelée lève une exception, il faut la gérer / la simuler, etc.
r e
ch n’appelle pas du tout la méthode de la
doReturn et
classe r©
A
éelle.
doThrow
JUnit
@Test
void testSommeCarre() {
doAnswer((invocation) -> {
Integer entier = [Link](0);
H I ©
return entier * entier;
UEL
}).when(calculService).carre([Link]());
O
f E LM
assertTrue([Link](2, 3) == 13, "calcul exact");
}
ch r e
©A
JUnit
@Test
void testSommeCarre() {
doAnswer((invocation) -> {
Integer entier = [Link](0);
H I ©
return entier * entier;
UEL
}).when(calculService).carre([Link]());
O
f E LM
assertTrue([Link](2, 3) == 13, "calcul exact");
}
ch r e
©A
Question
JUnit
Réponse
Utiliser ArgumentCaptor
H I ©
UEL
O
f E LM
ch r e
©A
JUnit
Réponse
Utiliser ArgumentCaptor
H I ©
UEL
O
ArgumentCaptor ?
f E LM
r e
h verify pour capturer les paramètres
passés © Amcéthode
utilisé avec la m
à une
éthode
simulée.
particulièrement utile lorsque nous ne pouvons pas accéder à un
paramètre en dehors de la méthode simulée.
JUnit
Exemple
@Test
void testSommeCarre() {
ArgumentCaptor<Integer> nbr = [Link]([Link]);
doAnswer((invocation) -> {
H I ©
EL
Integer entier = [Link](0);
return entier * entier;
}).when(calculService).carre([Link]());
O U
f E LM
assertTrue([Link](2, 3) == 13, "calcul exact");
verify(calculService, times(2)).carre([Link]());
r e
assertEquals(2, [Link]().get(0));
ch
©A
assertEquals(3, [Link]().get(1));
}
JUnit
Exemple
@Test
void testSommeCarre() {
ArgumentCaptor<Integer> nbr = [Link]([Link]);
doAnswer((invocation) -> {
H I ©
EL
Integer entier = [Link](0);
return entier * entier;
}).when(calculService).carre([Link]());
O U
f E LM
assertTrue([Link](2, 3) == 13, "calcul exact");
verify(calculService, times(2)).carre([Link]());
r e
assertEquals(2, [Link]().get(0));
ch
©A
assertEquals(3, [Link]().get(1));
}
JUnit
Explication
ArgumentCaptor<Integer> nbr =
[Link]([Link]) permet de déclarer un capteur
d’argument de type Integer.
H I ©
EL
[Link]() permet de capturer les arguments de type entier.
O U
[Link]() retourne les arguments capturés de type entier.
f E LM
ch r e
©A
JUnit
Explication
ArgumentCaptor<Integer> nbr =
[Link]([Link]) permet de déclarer un capteur
d’argument de type Integer.
H I ©
EL
[Link]() permet de capturer les arguments de type entier.
O U
[Link]() retourne les arguments capturés de type entier.
f E LM
ch r e
Remarques ©A
Si une méthode prend plusieurs arguments de types différents, alors il faut déclarer un
capteur d’arguments par type.
JUnit
H I ©
UEL
O
f E LM
ch r e
©A
JUnit
H I ©
UEL
O
Remarques
f E LM
r e
ch @Mock, il faut soit :
Pour activer l’annotation
A
appeler© la méthode initMocks (ou openMocks depuis Mockito
3).
annoter la classe de test par @ExtendWith.
JUnit
Activons l’annotation @Mock (Pour Mockito 2, remplacez openMocks par
initMocks)
class CalculTest {
Calcul calcul;
H I ©
UEL
@Mock
O
CalculService calculService;
f E LM
@BeforeEach
ch r e
©A
void setUp() throws Exception {
[Link](this);
calcul = new Calcul(calculService);
}
// + le code précédent
JUnit
On peut aussi remplacer l’appel de la méthode openMocks par
l’annotation @ExtendWith([Link])
@ExtendWith([Link])
class CalculTest {
H I ©
Calcul calcul;
U EL
O
@Mock
f E LM
CalculService calculService;
ch r e
@BeforeEach
©A
void setUp() throws Exception {
calcul = new Calcul(calculService);
}
// + le code précédent
JUnit
On peut aussi automatiser l’injection du mock dans le constructeur de
la classe Calcul en utilisant l’annotation @InjectMocks
@ExtendWith([Link])
class CalculTest {
H I ©
@Mock
U EL
CalculService calculService;
O
f E LM
@InjectMocks
Calcul calcul;
ch r e
@BeforeEach ©A
void setUp() throws Exception {
}
// + le code précédent
@ExtendWith([Link])
class PointTest {
@Spy
Point pointMock = new Point(2, 2);
@BeforeAll
static void setUpBeforeClass() throws Exception {
H I ©
EL
}
O U
LM
@AfterAll
static void tearDownAfterClass() throws Exception {
}
r e f E
ch
©A
@BeforeEach
void setUp() throws Exception {
}
@AfterEach
void tearDown() throws Exception {
}
// + les tests
JUnit
On peut aussi déclarer le capteur avec @Captor
@ExtendWith([Link])
class CalculTest {
@Mock
CalculService calculService;
@InjectMocks
Calcul calcul;
H I ©
@Captor
ArgumentCaptor<Integer> nbr;
UEL
O
LM
@BeforeEach
void setUp() throws Exception {
}
r e f E
@Test
ch
©A
void testSommeCarre() {
doAnswer((invocation) -> {
Integer entier = [Link](0);
return entier * entier;
}).when(calculService).carre([Link]());
assertTrue([Link](2, 3) == 13, "calcul exact");
verify(calculService, times(2)).carre([Link]());
assertEquals(2, [Link]().get(0));
assertEquals(3, [Link]().get(1));
}
JUnit
JUnit
Vérifier l’existence des deux répertoires
...
H I ©
UEL
O
f E LM
ch r e
©A
JUnit
Vérifier l’existence des deux répertoires
...
H I ©
UEL
O
f E
S’il n’y a pas de src/main/java ou src/test/java LM
ch r e
©A
Faire clic droit sur le projet
JUnit
H I ©
Ajouter les propriétés suivantes dans la section properties de [Link]
<properties>
U EL
<[Link]>UTF-8</[Link]>
O
LM
<[Link]>5.7.0</[Link]>
e E
<[Link]>1.7.0</[Link]>
f
<[Link]>3.7.7</[Link]>
r
</properties>
ch
©A
JUnit
Ajouter les dépendances suivantes dans la section dependencies de [Link]
<dependency>
<groupId>[Link]</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${[Link]}</version>
<scope>test</scope>
H I ©
EL
</dependency>
<dependency>
O U
<groupId>[Link]</groupId>
f E LM
<artifactId>junit-jupiter</artifactId>
r e
<version>${[Link]}</version>
ch
©A
<scope>test</scope>
</dependency>
dependency>
<groupId>[Link]</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${[Link]}</version>
<scope>test</scope>
</dependency>
JUnit
Pour tester
Déplacez le package [Link] du projet précédent
H I ©
dans src/main/java.
UEL
O
Déplacez le package [Link] dans
f E LM
ch r e
src/test/java et renommez le [Link].
©A
Annotez les classes de test par
@RunWith([Link]).
JUnit
Ajoutez l’annotation @RunWith([Link]) à la
classe CalculTest puis lancez le test
package [Link];
H I ©
EL
import [Link];
OU
import [Link];
L M
f E
// + les imports précédents
e
A chr
©
@ExtendWith([Link])
@RunWith([Link])
class CalculTest {
// + le code précédent
JUnit
import [Link];
H I ©
U EL
O
LM
// + les imports précédents
r e f
@DisplayName("Test de la classe Calcul") E
ch
©A
@ExtendWith([Link])
@RunWith([Link])
class CalculTest {
// + tout le code précédent
JUnit
JUnit
JUnit
Utiliser @RepeatedTest pour répéter un test plusieurs fois
@RepeatedTest(3)
void testSomme(RepetitionInfo repetitionInfo) {
assertNotEquals(7, [Link](repetitionInfo.
H I ©
EL
getCurrentRepetition(),3));
}
O U
f E LM
ch r e
©A
JUnit
Utiliser @RepeatedTest pour répéter un test plusieurs fois
@RepeatedTest(3)
void testSomme(RepetitionInfo repetitionInfo) {
assertNotEquals(7, [Link](repetitionInfo.
H I ©
EL
getCurrentRepetition(),3));
}
O U
f E LM
ch r e
Explication ©A
Il faut remplacer @Test par @RepeatedTest.
Pour récupérer l’index de l’itération courante, on déclare un objet
de type RepetitionInfo.
JUnit
JUnit
Utiliser @ParameterizedTest pour paramétrer un test
O U
f E LM
ch r e
©A
JUnit
Utiliser @ParameterizedTest pour paramétrer un test
O U
f E LM
Explication
ch r e
©A
Il faut remplacer @Test par @ParameterizedTest.
Cette méthode sera testée deux fois : une fois pour la valeur 2 et une fois pour la valeur 3.
JUnit
©A
<scope>test</scope>
</dependency>
JUnit
JUnit
Pour activer ou désactiver un test selon le système d’exploitation, on
utilise soit @DisabledOnOs soit @EnabledOnOs
@Test
@DisabledOnOs(MAC)
void testSommeCarre() {
H I ©
EL
...
}
O U
f E LM
ch r e
©A
JUnit
Pour activer ou désactiver un test selon le système d’exploitation, on
utilise soit @DisabledOnOs soit @EnabledOnOs
@Test
@DisabledOnOs(MAC)
void testSommeCarre() {
H I ©
EL
...
}
O U
f E LM
r
ch MAC e
Il faut importer la constante
import static
A
© [Link];
JUnit
Pour activer ou désactiver un test selon le système d’exploitation, on
utilise soit @DisabledOnOs soit @EnabledOnOs
@Test
@DisabledOnOs(MAC)
void testSommeCarre() {
H I ©
EL
...
}
O U
f E LM
r
ch MAC e
Il faut importer la constante
import static
A
© [Link];
JUnit
Pour activer ou désactiver un test selon la version de JRE, on utilise soit
@DisabledOnJre soit @EnabledOnJre
@Test
@DisabledOnOs(MAC)
@EnabledOnJre(JAVA_10)
void testSommeCarre() {
H I ©
...
U EL
}
O
f E LM
ch r e
©A
JUnit
Pour activer ou désactiver un test selon la version de JRE, on utilise soit
@DisabledOnJre soit @EnabledOnJre
@Test
@DisabledOnOs(MAC)
@EnabledOnJre(JAVA_10)
void testSommeCarre() {
H I ©
...
U EL
}
O
f E LM
r e
ch JAVA 10
A
Il faut importer la constante
©
import static [Link].JAVA_10;
JUnit
Pour activer ou désactiver un test selon la version de JRE, on utilise soit
@DisabledOnJre soit @EnabledOnJre
@Test
@DisabledOnOs(MAC)
@EnabledOnJre(JAVA_10)
void testSommeCarre() {
H I ©
...
U EL
}
O
f E LM
r e
ch JAVA 10
A
Il faut importer la constante
©
import static [Link].JAVA_10;
JUnit
Pour activer ou désactiver un test selon la valeur d’un test logique (on peut
même utiliser une expression régulière), on utilise soit @DisabledIf soit
@EnabledIf
H I ©
U EL
@Test
O
@DisabledOnOs(MAC)
@DisabledIf("2 * 3 > 4")
f E LM
void testSommeCarre() {
ch r e
©A
...
}
JUnit
Objectif
H I ©
U EL
O
f E LM
ch r e
©A
JUnit
Objectif
H I ©
U EL
O
f E LM
Pour cela, il faut installer un plugin Eclipse EclEmma
.
ch r e
©A
Aller dans Help > Install New Software > Add.
JUnit