Présentation

Le but de ces exercices est de réaliser le test d'une application complète dont le but est de présenter les résultats des match de pro A

L'application permet de :

  • Récupérer les résultats et les statistiques des derniers matchs joués via le web service de la LNB
  • Calculer un certain nombre de statistiques sur les joueurs et les match
  • Afficher les statistiques des match dans une ihm développée en Swing

Les sources de l'application dont disponnibles sur gitlab :

git clone git@gitlab.com:julien-gauchet/tests-unitaires-exercices.git

Vous pouvez également les télécharger ici : Sources tests unitaires


Tests de la couche services

Un service fr.julien.formation.basket.services.CalculStatistiquesService permet de calculer :

  • Le nombre de points d'un joueur au cours d'un match
  • L'évaluation d'un joueur : points + rebonds + passes décisives + interceptions + contres + tirs réussis - tirs ratés - ballons perdus

Le but de l'exercice et de :

  1. Déterminer quelles méthodes et quelles classes doivent être testées pour le service et les classes métier utilisées
  2. Réaliser les tests et corriger les erreurs éventuelles détectées
  3. Se poser des questions sur la qualité du jeu de tests

Les classes à tester sont :

  • CalculStatistiquesService : de facon évidente
  • Joueur : pour la méthode equals()
  • Equipe : pour la méthode equals()
package fr.julien.formation.basket.services.statistiques;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.model.BilanJoueur;
import fr.julien.formation.basket.model.Equipe;
import fr.julien.formation.basket.model.Joueur;

public class CalculStatistiqueServiceTest {
		@Test
		public void testerCalculScore() {
			Joueur kyle = new Joueur("MCALARNEY", "Kyle", new Equipe("OLB"));
			BilanJoueur bilan = new BilanJoueur(kyle, 1, 1, 7, 6, 7, 2, 3, 5, 2, 1, 1, 2);
			Assertions.assertEquals(19, CalculStatistiquesService.getInstance().calculerScore(bilan));
			Assertions.assertEquals(20, CalculStatistiquesService.getInstance().calculerEvaluation(bilan));
		}
}
package fr.julien.formation.basket.model;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class EquipeTest {
	
	@Test
	public void testerEquals() {
		Equipe e1 = new Equipe("Orléans");
		Equipe e2 = new Equipe("Orléans");
		Equipe e3 = new Equipe("ASVEL");
		Assertions.assertEquals(true, e1.equals(e2));
		Assertions.assertEquals(false, e1.equals(e3));
	}
}
package fr.julien.formation.basket.model;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class JoueurTest {

	@Test
	public void testerEquals() {
		Joueur kyle = new Joueur("MCALARNEY", "Kyle", new Equipe("OLB"));
		Joueur kyle2 = new Joueur("MCALARNEY", "Kyle", new Equipe("OLB"));
		Joueur kyle3 = new Joueur("MCALARNEY", "Kyle", new Equipe("Monaco"));
		Joueur kyle4 = new Joueur("MCALARNEY", "Autre", new Equipe("OLB"));
		Joueur cellus = new Joueur("SOMMERVILLE", "Marcellus", new Equipe("OLB"));
		Joueur cellus2 = new Joueur("SOMMERVILLE", "Kyle", new Equipe("OLB"));
		Assertions.assertEquals(true, kyle.equals(kyle2));
		Assertions.assertEquals(false, kyle.equals(kyle3));
		Assertions.assertEquals(false, kyle.equals(kyle4));
		Assertions.assertEquals(false, kyle.equals(cellus));
		Assertions.assertEquals(false, kyle.equals(cellus2));
	}
}

Le jeu de test est de qualité si :

  • La suppression d'un Assert a forcément un impact négatif sur la couverture du code : nous n'avons donc pas deux assert qui vérifient la même condition. Dans le cas contraire, nous avons un jeu de test trop lourd.
  • Les méthodes que nous avons ciblé sont globalement bien couvertes : en particulier les méthodes equals() dans lesquelles beaucoup de if s'enchainent : il faudrait couvrir au moins l'ensemble des cas non triviaux (un objet est null)
  • Aucune méthode get ou set n'a été testée, ni les constructeurs. Ces méthodes fonctionnent forcément. Une erreur classique est d'appeler un setter quelconque setValeur("valeur") et de faire un Assert.assertEquals("valeur", getValeur()) ce test ne peut pas échouer il n'apporte que de la complexité superfue

Test des daos

Le test de le couche DAO est plus complexe, il demande de faire appel à une base de données. Nous pouvons pour cela utiliser un schéma dédié de notre base, mais dans le cas présent, nous allons travailler sur une base h2

Le but de cet exercice est d'utiliser une base de données h2 pour tester les daos :

  • fr.julien.formation.basket.dao.BilansDao qui permet d'accéder à la table contenant les bilans des match
  • fr.julien.formation.basket.dao.MatchDao qui permet d'accéder à la table contenant les match
Diagramme de la base de données

Avec DBUnit

La création des fichiers suivants est nécéssaire

  • Un fichier src/test/resources/init_database_test.sql qui contient les instructions permettant de créer la base de données de test (script commun à tous les tests)
  • Un fichier src/test/resources/datasets/[NomTest].xml par classe de test qui contient les instructions permettant d'initialiser la base pour un test particulier
  • Un fichier src/test/resources/datasets/[NomTest]Resultat.xml par classe de test qui contient les tables que nous attendons en sortie
-- src/test/resources/init_database_test.sql
DROP TABLE IF EXISTS bilans CASCADE;
DROP TABLE IF EXISTS joueurs CASCADE;
DROP TABLE IF EXISTS equipes CASCADE;
DROP TABLE IF EXISTS matchs CASCADE;

CREATE TABLE matchs (
	id INT PRIMARY KEY
);

CREATE TABLE equipes (
	id INT PRIMARY KEY,
	nom VARCHAR
);

CREATE TABLE joueurs (
	id INT PRIMARY KEY,
	nom VARCHAR,
	prenom VARCHAR,
	id_equipe INT REFERENCES equipes(id)
);

CREATE TABLE bilans (
	id_match INT,
	id_joueur INT REFERENCES joueurs(id),
	lancer_francs INT,
	lancer_francs_reussis INT,
	deux_points INT,
	deux_points_reussis INT,
	trois_points INT,
	trois_points_reussis INT,
	rebonds INT,
	fautes INT,
	passes_decisives INT,
	ballons_perdus INT,
	interceptions INT,
	contres INT
);
<!-- BilansDaoTest.xml -->
<?xml version="1.0" encoding="UTF-8"?>  
<dataset>  
	<equipes id="1" nom="Orléans" />
	<equipes id="2" nom="Limoges" />
	
	<joueurs id="201" nom="CAMARA" prenom="Ousmane" id_equipe="2" />
	<joueurs id="202" nom="JONES" prenom="Joseph" id_equipe="2" />
	<joueurs id="203" nom="PREPELIC" prenom="Klemen" id_equipe="2" />
	<joueurs id="204" nom="WOJCIECHOWSKI" prenom="Mathieu" id_equipe="2" />
	<joueurs id="205" nom="WOOD" prenom="Dashaun" id_equipe="2" />
	<joueurs id="206" nom="DELAGE" prenom="Benjamin" id_equipe="2" />
	<joueurs id="207" nom="DUPORT" prenom="Romain" id_equipe="2" />
	<joueurs id="208" nom="FAIR" prenom="C.J" id_equipe="2" />
	<joueurs id="209" nom="MUNANGA" prenom="Shekinah" id_equipe="2" />
	<joueurs id="210" nom="RANDLE" prenom="Jerome" id_equipe="2" />
	<joueurs id="211" nom="ZERBO" prenom="Fréjus" id_equipe="2" />
	<joueurs id="101" nom="DOWNS" prenom="Micah" id_equipe="1" />
	<joueurs id="102" nom="LOUBAKI" prenom="Luc" id_equipe="1" />
	<joueurs id="103" nom="MILOSEVIC" prenom="Nemanja" id_equipe="1" />
	<joueurs id="104" nom="McALARNEY" prenom="Kyle" id_equipe="1" />
	<joueurs id="105" nom="OLASENI" prenom="Gabe" id_equipe="1" />
	<joueurs id="106" nom="JOSEPH" prenom="Georgi" id_equipe="1" />
	<joueurs id="107" nom="MENDY" prenom="Antoine" id_equipe="1" />
	<joueurs id="108" nom="PRINCE" prenom="John" id_equipe="1" />
	<joueurs id="109" nom="SOMMERVILLE" prenom="Marcellus" id_equipe="1" />
	<joueurs id="110" nom="SYLLA" prenom="Abdel Kader" id_equipe="1" />
	<joueurs id="111" nom="VINCENT" prenom="Thomas" id_equipe="1" />
	
	<matchs id="34" />
	
	<bilans id_match="34" id_joueur="201" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="6" deux_points="14" trois_points_reussis="0" trois_points="0" rebonds="8" fautes="3" passes_decisives="1"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="202" lancer_francs_reussis="0" lancer_francs="1" deux_points_reussis="2" deux_points="3"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="2" passes_decisives="1"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="203" lancer_francs_reussis="4" lancer_francs="4" deux_points_reussis="0" deux_points="3"  trois_points_reussis="3" trois_points="9" rebonds="1" fautes="4" passes_decisives="5"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="204" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="0"  trois_points_reussis="2" trois_points="2" rebonds="8" fautes="4" passes_decisives="2"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="205" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="4"  trois_points_reussis="1" trois_points="7" rebonds="2" fautes="3" passes_decisives="2"  ballons_perdus="3" interceptions="3" contres="0" />
	<bilans id_match="34" id_joueur="206" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="0"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="207" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="3"  trois_points_reussis="1" trois_points="3" rebonds="2" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="208" lancer_francs_reussis="2" lancer_francs="4" deux_points_reussis="3" deux_points="4"  trois_points_reussis="0" trois_points="3" rebonds="5" fautes="1" passes_decisives="0"  ballons_perdus="0" interceptions="1" contres="1" />
	<bilans id_match="34" id_joueur="209" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="3"  trois_points_reussis="1" trois_points="1" rebonds="3" fautes="2" passes_decisives="0"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="210" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="4" deux_points="7"  trois_points_reussis="2" trois_points="4" rebonds="1" fautes="0" passes_decisives="3"  ballons_perdus="4" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="211" lancer_francs_reussis="3" lancer_francs="4" deux_points_reussis="1" deux_points="3"  trois_points_reussis="0" trois_points="0" rebonds="1" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="101" lancer_francs_reussis="1" lancer_francs="2" deux_points_reussis="2" deux_points="2"  trois_points_reussis="3" trois_points="5" rebonds="5" fautes="0" passes_decisives="4"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="102" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="1"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="0" passes_decisives="0"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="103" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="2"  trois_points_reussis="1" trois_points="2" rebonds="1" fautes="1" passes_decisives="1"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="104" lancer_francs_reussis="3" lancer_francs="3" deux_points_reussis="0" deux_points="2"  trois_points_reussis="1" trois_points="4" rebonds="3" fautes="1" passes_decisives="2"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="105" lancer_francs_reussis="2" lancer_francs="2" deux_points_reussis="4" deux_points="10" trois_points_reussis="0" trois_points="0" rebonds="6" fautes="2" passes_decisives="2"  ballons_perdus="0" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="106" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="1"  trois_points_reussis="1" trois_points="1" rebonds="3" fautes="2" passes_decisives="1"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="107" lancer_francs_reussis="1" lancer_francs="1" deux_points_reussis="5" deux_points="7"  trois_points_reussis="2" trois_points="7" rebonds="3" fautes="0" passes_decisives="2"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="108" lancer_francs_reussis="1" lancer_francs="2" deux_points_reussis="7" deux_points="8"  trois_points_reussis="1" trois_points="2" rebonds="5" fautes="2" passes_decisives="10" ballons_perdus="2" interceptions="4" contres="0" />
	<bilans id_match="34" id_joueur="109" lancer_francs_reussis="4" lancer_francs="4" deux_points_reussis="4" deux_points="6"  trois_points_reussis="0" trois_points="1" rebonds="3" fautes="3" passes_decisives="3"  ballons_perdus="2" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="110" lancer_francs_reussis="0" lancer_francs="1" deux_points_reussis="5" deux_points="7"  trois_points_reussis="0" trois_points="0" rebonds="5" fautes="2" passes_decisives="4"  ballons_perdus="2" interceptions="2" contres="0" />
	<bilans id_match="34" id_joueur="111" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="1"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="1" passes_decisives="0"  ballons_perdus="1" interceptions="0" contres="0" />

</dataset>
<!-- BilansDaoTestResultat.xml -->
<?xml version="1.0" encoding="UTF-8"?>  
<dataset>  
	<bilans id_match="34" id_joueur="201" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="6" deux_points="14" trois_points_reussis="0" trois_points="0" rebonds="8" fautes="3" passes_decisives="1"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="202" lancer_francs_reussis="0" lancer_francs="1" deux_points_reussis="2" deux_points="3"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="2" passes_decisives="1"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="203" lancer_francs_reussis="4" lancer_francs="4" deux_points_reussis="0" deux_points="3"  trois_points_reussis="3" trois_points="9" rebonds="1" fautes="4" passes_decisives="5"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="204" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="0"  trois_points_reussis="2" trois_points="2" rebonds="8" fautes="4" passes_decisives="2"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="205" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="4"  trois_points_reussis="1" trois_points="7" rebonds="2" fautes="3" passes_decisives="2"  ballons_perdus="3" interceptions="3" contres="0" />
	<bilans id_match="34" id_joueur="206" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="0"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="207" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="3"  trois_points_reussis="1" trois_points="3" rebonds="2" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="208" lancer_francs_reussis="2" lancer_francs="4" deux_points_reussis="3" deux_points="4"  trois_points_reussis="0" trois_points="3" rebonds="5" fautes="1" passes_decisives="0"  ballons_perdus="0" interceptions="1" contres="1" />
	<bilans id_match="34" id_joueur="209" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="3"  trois_points_reussis="1" trois_points="1" rebonds="3" fautes="2" passes_decisives="0"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="210" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="4" deux_points="7"  trois_points_reussis="2" trois_points="4" rebonds="1" fautes="0" passes_decisives="3"  ballons_perdus="4" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="211" lancer_francs_reussis="3" lancer_francs="4" deux_points_reussis="1" deux_points="3"  trois_points_reussis="0" trois_points="0" rebonds="1" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="101" lancer_francs_reussis="1" lancer_francs="2" deux_points_reussis="2" deux_points="2"  trois_points_reussis="3" trois_points="5" rebonds="5" fautes="0" passes_decisives="4"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="102" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="1"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="0" passes_decisives="0"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="103" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="2"  trois_points_reussis="1" trois_points="2" rebonds="1" fautes="1" passes_decisives="1"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="104" lancer_francs_reussis="3" lancer_francs="3" deux_points_reussis="0" deux_points="2"  trois_points_reussis="1" trois_points="4" rebonds="3" fautes="1" passes_decisives="2"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="105" lancer_francs_reussis="2" lancer_francs="2" deux_points_reussis="4" deux_points="10" trois_points_reussis="0" trois_points="0" rebonds="6" fautes="2" passes_decisives="2"  ballons_perdus="0" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="106" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="1"  trois_points_reussis="1" trois_points="1" rebonds="3" fautes="2" passes_decisives="1"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="107" lancer_francs_reussis="1" lancer_francs="1" deux_points_reussis="5" deux_points="7"  trois_points_reussis="2" trois_points="7" rebonds="3" fautes="0" passes_decisives="2"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="108" lancer_francs_reussis="1" lancer_francs="2" deux_points_reussis="7" deux_points="8"  trois_points_reussis="1" trois_points="2" rebonds="5" fautes="2" passes_decisives="10" ballons_perdus="2" interceptions="4" contres="0" />
	<bilans id_match="34" id_joueur="109" lancer_francs_reussis="4" lancer_francs="4" deux_points_reussis="4" deux_points="6"  trois_points_reussis="0" trois_points="1" rebonds="3" fautes="3" passes_decisives="3"  ballons_perdus="2" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="110" lancer_francs_reussis="0" lancer_francs="1" deux_points_reussis="5" deux_points="7"  trois_points_reussis="0" trois_points="0" rebonds="5" fautes="2" passes_decisives="4"  ballons_perdus="2" interceptions="2" contres="0" />
	<bilans id_match="34" id_joueur="111" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="1"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="1" passes_decisives="0"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="0" lancer_francs_reussis="2" lancer_francs="1" deux_points_reussis="4" deux_points="3"  trois_points_reussis="6" trois_points="5" rebonds="7" fautes="8" passes_decisives="9"  ballons_perdus="10" interceptions="11" contres="12" />
</dataset>
package fr.julien.formation.basket.dao.dbunit;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;

import org.dbunit.Assertion;
import org.dbunit.assertion.comparer.value.ValueComparer;
import org.dbunit.assertion.comparer.value.ValueComparers;
import org.dbunit.assertion.comparer.value.builder.ColumnValueComparerMapBuilder;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.dao.BilansDao;
import fr.julien.formation.basket.exception.BasketException;
import fr.julien.formation.basket.model.BilanJoueur;
import fr.julien.formation.basket.model.Equipe;
import fr.julien.formation.basket.model.Joueur;

public class BilansDaoTest {
	private Connection cnx;

	@BeforeEach
	public void setUp() {
		JdbcDataSource dataSource = new JdbcDataSource();
		dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
		dataSource.setUser("sa");
		dataSource.setPassword("");
		try {
			cnx = dataSource.getConnection();
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
			IDatabaseConnection dbUnitConnection = new DatabaseConnection(cnx);
			FlatXmlDataSetBuilder xmlDSBuilder = new FlatXmlDataSetBuilder();
			xmlDSBuilder.setCaseSensitiveTableNames(false);
			InputStream inputStreamXML = new FileInputStream("src/test/resources/datasets/BilansDaoTest.xml");
			IDataSet dataSet = xmlDSBuilder.build(inputStreamXML);
			DatabaseOperation.CLEAN_INSERT.execute(dbUnitConnection, dataSet);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
   }

    @AfterEach
	public void tearDown() {
		try {
			cnx.close();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testerSelection() {
		try {
			List<BilanJoueur> bilans = BilansDao.getInstance().getBilansByMatch(cnx, 34);
			Assertions.assertEquals(22, bilans.size());
			Assertions.assertEquals(new Joueur("CAMARA", "Ousmane", new Equipe("Limoges")), bilans.get(0).getJoueur());
			Assertions.assertEquals(0, bilans.get(0).getLancerFrancsReussis());
			Assertions.assertEquals(0, bilans.get(0).getLancerFrancs());
			Assertions.assertEquals(6, bilans.get(0).getDeuxPointsReussis());
			Assertions.assertEquals(14, bilans.get(0).getDeuxPoints());
			Assertions.assertEquals(0, bilans.get(0).getTroisPointsReussis());
			Assertions.assertEquals(0, bilans.get(0).getTroisPoints());
			Assertions.assertEquals(1, bilans.get(0).getPassesDecisives());
			Assertions.assertEquals(1, bilans.get(0).getBallonsPerdus());
			Assertions.assertEquals(3, bilans.get(0).getFautes());
			Assertions.assertEquals(8, bilans.get(0).getRebonds());
			Assertions.assertEquals(0, bilans.get(0).getInterceptions());
			Assertions.assertEquals(0, bilans.get(0).getContres());
		}
		catch (BasketException e) {
			e.printStackTrace();
			Assertions.fail();
		}
    }

	@Test
	public void testerInsertion() {
		try {
			try (Statement stmt = cnx.createStatement()) {
				stmt.executeUpdate("INSERT INTO joueurs(id, nom, prenom, id_equipe) VALUES (0, 'Gauchet', 'Julien', 2)");
			}
			BilanJoueur b = new BilanJoueur(new Joueur("Gauchet", "Julien", new Equipe("Orléans")), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
			BilansDao.getInstance().inserer(cnx, b, 34);
			IDatabaseConnection dbUnitConnection = new DatabaseConnection(cnx);
			QueryDataSet partialDataSet = new QueryDataSet(dbUnitConnection);
			partialDataSet.addTable("bilans", "SELECT * FROM bilans");
			FlatXmlDataSetBuilder xmlDSBuilder = new FlatXmlDataSetBuilder();
			xmlDSBuilder.setCaseSensitiveTableNames(false);
			InputStream inputStreamXML = new FileInputStream("src/test/resources/datasets/BilansDaoTestResultat.xml");
			IDataSet dataSet = xmlDSBuilder.build(inputStreamXML);
			ITable tableAttendue = dataSet.getTable("bilans");
			Map<String, ValueComparer> columnValueComparers = new ColumnValueComparerMapBuilder().add("lancer_francs_reussis", ValueComparers.isActualEqualToExpected).add("lancer_francs", ValueComparers.isActualEqualToExpected).build();
			Assertion.assertWithValueComparer(tableAttendue, partialDataSet.getTable("bilans"), ValueComparers.isActualEqualToExpected, columnValueComparers);
		}
		catch (Exception e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}
}
<!-- MatchsDaoTestResultat.xml -->
<?xml version="1.0" encoding="UTF-8"?>  
<dataset>  
	<matchs id="1" />
</dataset>
package fr.julien.formation.basket.dao.dbunit;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;

import org.dbunit.Assertion;
import org.dbunit.assertion.comparer.value.ValueComparer;
import org.dbunit.assertion.comparer.value.ValueComparers;
import org.dbunit.assertion.comparer.value.builder.ColumnValueComparerMapBuilder;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.dao.MatchDao;

public class MatchsDaoTest {

	private Connection cnx;

	@BeforeEach
	public void setUp() {
		JdbcDataSource dataSource = new JdbcDataSource();
		dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
		dataSource.setUser("sa");
		dataSource.setPassword("");
		try {
			cnx = dataSource.getConnection();
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	@AfterEach
	public void tearDown() {
		try {
			cnx.close();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testerInsertion() {
		try {
			MatchDao.getInstance().inserer(cnx, 1);
			try (Statement stmt = cnx.createStatement()) {
				IDatabaseConnection dbUnitConnection = new DatabaseConnection(cnx);
				QueryDataSet partialDataSet = new QueryDataSet(dbUnitConnection);
				partialDataSet.addTable("matchs", "SELECT * FROM matchs");
				FlatXmlDataSetBuilder xmlDSBuilder = new FlatXmlDataSetBuilder();
				xmlDSBuilder.setCaseSensitiveTableNames(false);
				InputStream inputStreamXML = new FileInputStream("src/test/resources/datasets/MatchsDaoTestResultat.xml");
				IDataSet dataSet = xmlDSBuilder.build(inputStreamXML);
				ITable tableAttendue = dataSet.getTable("matchs");
				Map<String, ValueComparer> columnValueComparers = new ColumnValueComparerMapBuilder().build();
				Assertion.assertWithValueComparer(tableAttendue, partialDataSet.getTable("matchs"), ValueComparers.isActualEqualToExpected, columnValueComparers);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}
}

Avec un script SQL

La création des fichiers suivants est nécéssaire

  • Un fichier src/test/resources/init_database_test.sql qui contient les instructions permettant de créer la base de données de test (script commun à tous les tests)
  • Un fichier src/test/resources/data/[NomTest].sql par classe de test qui contient les instructions permettant d'initialiser la base pour un test particulier
-- src/test/resources/init_database_test.sql
DROP TABLE IF EXISTS bilans CASCADE;
DROP TABLE IF EXISTS joueurs CASCADE;
DROP TABLE IF EXISTS equipes CASCADE;
DROP TABLE IF EXISTS matchs CASCADE;

CREATE TABLE matchs (
	id INT PRIMARY KEY
);

CREATE TABLE equipes (
	id INT PRIMARY KEY,
	nom VARCHAR
);

CREATE TABLE joueurs (
	id INT PRIMARY KEY,
	nom VARCHAR,
	prenom VARCHAR,
	id_equipe INT REFERENCES equipes(id)
);

CREATE TABLE bilans (
	id_match INT,
	id_joueur INT REFERENCES joueurs(id),
	lancer_francs INT,
	lancer_francs_reussis INT,
	deux_points INT,
	deux_points_reussis INT,
	trois_points INT,
	trois_points_reussis INT,
	rebonds INT,
	fautes INT,
	passes_decisives INT,
	ballons_perdus INT,
	interceptions INT,
	contres INT
);
-- Fichiers d'initialisation des tests (identiques pour les deux tests)
INSERT INTO equipes(id, nom) 
VALUES 
	(1, 'Orléans'), 
	(2, 'Limoges');
INSERT INTO joueurs (id, nom, prenom, id_equipe)
VALUES 
	(201, 'CAMARA', 'Ousmane', 2),
	(202, 'JONES', 'Joseph', 2),
	(203, 'PREPELIC', 'Klemen', 2),
	(204, 'WOJCIECHOWSKI', 'Mathieu', 2),
	(205, 'WOOD', 'Dashaun', 2),
	(206, 'DELAGE', 'Benjamin', 2),
	(207, 'DUPORT', 'Romain', 2),
	(208, 'FAIR', 'C.J', 2),
	(209, 'MUNANGA', 'Shekinah', 2),
	(210, 'RANDLE', 'Jerome', 2),
	(211, 'ZERBO', 'Fréjus', 2),
	(101, 'DOWNS', 'Micah', 1),
	(102, 'LOUBAKI', 'Luc', 1),
	(103, 'MILOSEVIC', 'Nemanja', 1),
	(104, 'McALARNEY', 'Kyle', 1),
	(105, 'OLASENI', 'Gabe', 1),
	(106, 'JOSEPH', 'Georgi', 1),
	(107, 'MENDY', 'Antoine', 1),
	(108, 'PRINCE', 'John', 1),
	(109, 'SOMMERVILLE', 'Marcellus', 1),
	(110, 'SYLLA', 'Abdel Kader', 1),
	(111, 'VINCENT', 'Thomas', 1);
	
INSERT INTO matchs(id) VALUES (34);

INSERT INTO bilans (id_match, id_joueur, lancer_francs_reussis, lancer_francs, deux_points_reussis, deux_points, trois_points_reussis, trois_points, rebonds, fautes, passes_decisives,ballons_perdus, interceptions, contres)
VALUES 
	(34, 201, 0, 0, 6, 14, 0, 0, 8, 3, 1, 1, 0, 0),
	(34, 202, 0, 1, 2, 3, 0, 0, 0, 2, 1, 1, 0, 0),
	(34, 203, 4, 4, 0, 3, 3, 9, 1, 4, 5, 1, 0, 0),
	(34, 204, 0, 0, 0, 0, 2, 2, 8, 4, 2, 1, 0, 0),
	(34, 205, 0, 0, 2, 4, 1, 7, 2, 3, 2, 3, 3, 0),
	(34, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
	(34, 207, 0, 0, 1, 3, 1, 3, 2, 0, 0, 0, 0, 0),
	(34, 208, 2, 4, 3, 4, 0, 3, 5, 1, 0, 0, 1, 1),
	(34, 209, 0, 0, 2, 3, 1, 1, 3, 2, 0, 1, 1, 0),
	(34, 210, 0, 0, 4, 7, 2, 4, 1, 0, 3, 4, 0, 0),
	(34, 211, 3, 4, 1, 3, 0, 0, 1, 0, 0, 0, 1, 0),
	(34, 101, 1, 2, 2, 2, 3, 5, 5, 0, 4, 1, 0, 0),
	(34, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0),
	(34, 103, 0, 0, 2, 2, 1, 2, 1, 1, 1, 0, 0, 0),
	(34, 104, 3, 3, 0, 2, 1, 4, 3, 1, 2, 1, 1, 0),
	(34, 105, 2, 2, 4, 10, 0, 0, 6, 2, 2, 0, 1, 0),
	(34, 106, 0, 0, 1, 1, 1, 1, 3, 2, 1, 1, 1, 0),
	(34, 107, 1, 1, 5, 7, 2, 7, 3, 0, 2, 1, 1, 0),
	(34, 108, 1, 2, 7, 8, 1, 2, 5, 2, 10, 2, 4, 0),
	(34, 109, 4, 4, 4, 6, 0, 1, 3, 3, 3, 2, 0, 0),
	(34, 110, 0, 1, 5, 7, 0, 0, 5, 2, 4, 2, 2, 0),
	(34, 111, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0);
package fr.julien.formation.basket.dao.scripts;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.dao.BilansDao;
import fr.julien.formation.basket.exception.BasketException;
import fr.julien.formation.basket.model.BilanJoueur;
import fr.julien.formation.basket.model.Equipe;
import fr.julien.formation.basket.model.Joueur;

public class BilansDaoTest {

	private Connection cnx;

	@BeforeEach
	public void setUp() {
		JdbcDataSource dataSource = new JdbcDataSource();
		dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
		dataSource.setUser("sa");
		dataSource.setPassword("");
		try {
			cnx = dataSource.getConnection();
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/data/BilansDaoTest.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	@AfterEach
	public void tearDown() {
		try {
			cnx.close();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

 	@Test
	public void testerSelection() {
 		try {
			List<BilanJoueur> bilans = BilansDao.getInstance().getBilansByMatch(cnx, 34);
			Assertions.assertEquals(22, bilans.size());
			Assertions.assertEquals(new Joueur("CAMARA", "Ousmane", new Equipe("Limoges")), bilans.get(0).getJoueur());
			Assertions.assertEquals(0, bilans.get(0).getLancerFrancsReussis());
			Assertions.assertEquals(0, bilans.get(0).getLancerFrancs());
			Assertions.assertEquals(6, bilans.get(0).getDeuxPointsReussis());
			Assertions.assertEquals(14, bilans.get(0).getDeuxPoints());
			Assertions.assertEquals(0, bilans.get(0).getTroisPointsReussis());
			Assertions.assertEquals(0, bilans.get(0).getTroisPoints());
			Assertions.assertEquals(1, bilans.get(0).getPassesDecisives());
			Assertions.assertEquals(1, bilans.get(0).getBallonsPerdus());
			Assertions.assertEquals(3, bilans.get(0).getFautes());
			Assertions.assertEquals(8, bilans.get(0).getRebonds());
			Assertions.assertEquals(0, bilans.get(0).getInterceptions());
			Assertions.assertEquals(0, bilans.get(0).getContres());
		}
		catch (BasketException e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}

	@Test
	public void testerInsertion() {
		try {
			try (Statement stmt = cnx.createStatement()) {
				stmt.executeUpdate("INSERT INTO joueurs(id, nom, prenom, id_equipe) VALUES (0, 'Gauchet', 'Julien', 2)");
			}
			BilanJoueur b = new BilanJoueur(new Joueur("Gauchet", "Julien", new Equipe("Orléans")), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
			BilansDao.getInstance().inserer(cnx, b, 34);
			try (Statement stmt = cnx.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM bilans WHERE id_joueur=0")) {
				Assertions.assertTrue(rs.next());
				Assertions.assertEquals(2, rs.getInt("lancer_francs_reussis"));
			}
		}
		catch (BasketException | SQLException e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}
}
public class BilansDaoTest {

    private Connection cnx;

    @Before
    public void setUp() {
        JdbcDataSource dataSource = new JdbcDataSource();
        dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
        dataSource.setUser("sa");
        dataSource.setPassword("");
        try {
            cnx = dataSource.getConnection();
            try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
                RunScript.execute(cnx, br);
            }
            try (InputStreamReader fr = new FileReader(new File("src/test/resources/data/BilansDaoTest.sql")); BufferedReader br = new BufferedReader(fr)) {
                RunScript.execute(cnx, br);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    @After
    public void tearDown() {
        try {
            cnx.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testerSelection() {
        try {
            List<BilanJoueur> bilans = BilansDao.getInstance().getBilansByMatch(cnx, 34);
            Assert.assertEquals(22, bilans.size());
            Assert.assertEquals(new Joueur("CAMARA", "Ousmane", new Equipe("Limoges")), bilans.get(0).getJoueur());
            Assert.assertEquals(0, bilans.get(0).getLancerFrancsReussis());
            Assert.assertEquals(0, bilans.get(0).getLancerFrancs());
            Assert.assertEquals(6, bilans.get(0).getDeuxPointsReussis());
            Assert.assertEquals(14, bilans.get(0).getDeuxPoints());
            Assert.assertEquals(0, bilans.get(0).getTroisPointsReussis());
            Assert.assertEquals(0, bilans.get(0).getTroisPoints());
            Assert.assertEquals(1, bilans.get(0).getPassesDecisives());
            Assert.assertEquals(1, bilans.get(0).getBallonsPerdus());
            Assert.assertEquals(3, bilans.get(0).getFautes());
            Assert.assertEquals(8, bilans.get(0).getRebonds());
            Assert.assertEquals(0, bilans.get(0).getInterceptions());
            Assert.assertEquals(0, bilans.get(0).getContres());
        }
        catch (BasketException e) {
            e.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void testerInsertion() {
        try {
            try (Statement stmt = cnx.createStatement()) {
                stmt.executeUpdate("INSERT INTO joueurs(id, nom, prenom, id_equipe) VALUES (0, 'Gauchet', 'Julien', 2)");
            }
            BilanJoueur b = new BilanJoueur(new Joueur("Gauchet", "Julien", new Equipe("Orléans")), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
            BilansDao.getInstance().inserer(cnx, b, 34);
            try (Statement stmt = cnx.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM bilans WHERE id_joueur=0")) {
                Assert.assertTrue(rs.next());
                Assert.assertEquals(2, rs.getInt("lancer_francs_reussis"));
            }
        }
        catch (BasketException | SQLException e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
}

Création de mocks

Nous allons maintenant tester la classe fr.julien.formation.basket.services.MiseAJourMatchs qui fait appel à un web service non accessible hors production. Utilisez des mock pour réaliser le test de cette classe. Un refactoring est nécéssaire

Le web service fournit un résultat xml scructuré de la facon suivante :

<matchs journee="??">
	nomJoueur;prenomJoueur;nomEquipe;lancerFrancs;lancerFrancsReussis;deuxPoints;deuxPointsReussis;troisPoints;troisPointsReussis;rebonds;fautes;passesDecisives;ballonsPerdus;interceptions;contres
	nomJoueur;prenomJoueur;nomEquipe;lancerFrancs;lancerFrancsReussis;deuxPoints;deuxPointsReussis;troisPoints;troisPointsReussis;rebonds;fautes;passesDecisives;ballonsPerdus;interceptions;contres
</matchs>

Avec héritage

package fr.julien.formation.basket.services.matchs.heritage;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.model.Equipe;
import fr.julien.formation.basket.services.lnb.AccesWebServiceLNB;
import fr.julien.formation.basket.services.matchs.MiseAJourMatchs;

public class MiseAJourMatchsTest {

	private Connection cnx;

	@BeforeEach
	public void setUp() {
		JdbcDataSource dataSource = new JdbcDataSource();
		dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
		dataSource.setUser("sa");
		dataSource.setPassword("");
		try {
			cnx = dataSource.getConnection();
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	@AfterEach
	public void tearDown() {
		try {
			cnx.close();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testerMiseAJour() {
		try {
			AccesWebServiceLNB webService = new AccesWebServiceLNB() {
				@Override
				public String getReponse(String url, int journee) {
					StringBuilder sb = new StringBuilder();
					sb.append("<matchs journee=\"34\">");
					sb.append("SOMMERVILLE;Marcellus;Orléans;5;3;5;5;2;1;3;2;3;1;0;1");
					sb.append("</matchs>");
					return sb.toString();
				}
			};
			MiseAJourMatchs.getInstance().setAccesWebServiceLNB(webService);
			MiseAJourMatchs.getInstance().mettreAJour(cnx, new Equipe("Orléans"), 33);
			try (Statement stmt = cnx.createStatement()) {
				try (ResultSet rs = stmt.executeQuery("SELECT * FROM bilans WHERE id_match=33")) {
					Assertions.assertTrue(rs.next());
					Assertions.assertEquals(5, rs.getInt("lancer_francs"));
					Assertions.assertEquals(3, rs.getInt("lancer_francs_reussis"));
					Assertions.assertEquals(5, rs.getInt("deux_points"));
					Assertions.assertEquals(5, rs.getInt("deux_points_reussis"));
					Assertions.assertEquals(2, rs.getInt("trois_points"));
					Assertions.assertEquals(1, rs.getInt("trois_points_reussis"));
					Assertions.assertEquals(3, rs.getInt("rebonds"));
					Assertions.assertEquals(2, rs.getInt("fautes"));
					Assertions.assertEquals(3, rs.getInt("passes_decisives"));
					Assertions.assertEquals(1, rs.getInt("ballons_perdus"));
					Assertions.assertEquals(0, rs.getInt("interceptions"));
					Assertions.assertEquals(1, rs.getInt("contres"));
				}
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}
}

Avec l'utilisation de mockito

package fr.julien.formation.basket.services.matchs.easymock;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.easymock.EasyMock;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.model.Equipe;
import fr.julien.formation.basket.services.lnb.AccesWebServiceLNB;
import fr.julien.formation.basket.services.matchs.MiseAJourMatchs;

@DisplayName("Test des mises à jour avec Mockito")
public class MiseAJourMatchsTest {
	private Connection cnx;

	@BeforeEach
	public void setUp() {
		JdbcDataSource dataSource = new JdbcDataSource();
		dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
		dataSource.setUser("sa");
		dataSource.setPassword("");
		try {
			cnx = dataSource.getConnection();
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	@AfterEach
	public void tearDown() {
		try {
			cnx.close();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Test
	@DisplayName("Test global")
	public void testerMiseAJour() {
		try {
			AccesWebServiceLNB webService = EasyMock.createNiceMock(AccesWebServiceLNB.class);
			StringBuilder sb = new StringBuilder();
			sb.append("<matchs journee=\"34\">");
			sb.append("SOMMERVILLE;Marcellus;Orléans;5;3;5;5;2;1;3;2;3;1;0;1");
			sb.append("</matchs>");
			EasyMock.expect(webService.getReponse("http://www.lnb.fr/ws/journee/", 33)).andReturn(sb.toString());
			EasyMock.replay(webService);
			MiseAJourMatchs.getInstance().setAccesWebServiceLNB(webService);
			MiseAJourMatchs.getInstance().setAccesWebServiceLNB(webService);
			MiseAJourMatchs.getInstance().mettreAJour(cnx, new Equipe("Orléans"), 33);
			try (Statement stmt = cnx.createStatement()) {
				try (ResultSet rs = stmt.executeQuery("SELECT * FROM bilans WHERE id_match=33")) {
					Assertions.assertTrue(rs.next());
					Assertions.assertEquals(5, rs.getInt("lancer_francs"));
					Assertions.assertEquals(3, rs.getInt("lancer_francs_reussis"));
					Assertions.assertEquals(5, rs.getInt("deux_points"));
					Assertions.assertEquals(5, rs.getInt("deux_points_reussis"));
					Assertions.assertEquals(2, rs.getInt("trois_points"));
					Assertions.assertEquals(1, rs.getInt("trois_points_reussis"));
					Assertions.assertEquals(3, rs.getInt("rebonds"));
					Assertions.assertEquals(2, rs.getInt("fautes"));
					Assertions.assertEquals(3, rs.getInt("passes_decisives"));
					Assertions.assertEquals(1, rs.getInt("ballons_perdus"));
					Assertions.assertEquals(0, rs.getInt("interceptions"));
					Assertions.assertEquals(1, rs.getInt("contres"));
				}
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}
}

Que faire de l'ihm ?

Notre application contient une partie ihm : le test de l'ihm ne se fait pas grâce à des tests unitaires. Cependant, une partie du code de l'ihm peut être testée : a vous de l'identifier et de faire ce qu'il faut pour que cette partie soit désormais testable

public class TableauEquipe {

    private String nomEquipe;
    private List<List<String>> statistiques;

    public TableauEquipe() {
        this.statistiques = new ArrayList<>();
    }

    public TableauEquipe(String nomEquipe) {
        this.nomEquipe = nomEquipe;
        this.statistiques = new ArrayList<>();
    }

    /**
     * Méthode permettant d'accéder au nom de l'équipe
     * 
     * @return le nom de l'équipe
     */
    public String getNomEquipe() {
        return nomEquipe;
    }

    /**
     * Méthode permettant d'accéder aux statistiques
     * 
     * @return les statistiques
     */
    public List<List<String>> getStatistiques() {
        return statistiques;
    }

    public void setNomEquipe(String nomEquipe) {
        this.nomEquipe = nomEquipe;
    }

    public void setStatistiques(List<List<String>> statistiques) {
        this.statistiques = statistiques;
    }
}
public class TableauMatch {

    private TableauEquipe tableauEquipe1;
    private TableauEquipe tableauEquipe2;

    public TableauMatch(TableauEquipe tableauEquipe1, TableauEquipe tableauEquipe2) {
        super();
        this.tableauEquipe1 = tableauEquipe1;
        this.tableauEquipe2 = tableauEquipe2;
    }

    /**
     * Méthode permettant d'accéder au tableau de l'équipe 1
     * 
     * @return le tableau de l'équipe 1
     */
    public TableauEquipe getTableauEquipe1() {
        return tableauEquipe1;
    }

    /**
     * Méthode permettant d'accéder tableau de l'équipe 2
     * 
     * @return le tableau de l'équipe 2
     */
    public TableauEquipe getTableauEquipe2() {
        return tableauEquipe2;
    }
}
public class GenerationTableauMatch {

    private static GenerationTableauMatch instance = new GenerationTableauMatch();

    private GenerationTableauMatch() {
        super();
    }

    public TableauMatch genererTableauMatch(Connection cnx, int journee) throws BasketException {
        List<BilanJoueur> bilans = BilansDao.getInstance().getBilansByMatch(cnx, journee);
        String equipe1 = null;
        String equipe2 = null;
        TableauEquipe tableauEquipe1 = new TableauEquipe();
        TableauEquipe tableauEquipe2 = new TableauEquipe();
        for (BilanJoueur b : bilans) {
            if (equipe1 == null) {
                equipe1 = b.getJoueur().getEquipe().getNom();
                tableauEquipe1.setNomEquipe(equipe1);
            }
            else if (equipe2 == null && !b.getJoueur().getEquipe().getNom().equalsIgnoreCase(equipe1)) {
                equipe2 = b.getJoueur().getEquipe().getNom();
                tableauEquipe2.setNomEquipe(equipe2);
            }
            if (b.getJoueur().getEquipe().getNom().equals(equipe1)) {
                tableauEquipe1.getStatistiques().add(calculerScore(b));
            }
            else if (b.getJoueur().getEquipe().getNom().equals(equipe2)) {
                tableauEquipe2.getStatistiques().add(calculerScore(b));
            }
        }
        return new TableauMatch(tableauEquipe1, tableauEquipe2);
    }

    private List<String> calculerScore(BilanJoueur b) {
        List<String> stat = new ArrayList<>();
        int score = CalculStatistiquesService.getInstance().calculerScore(b);
        stat.add(b.getJoueur().toString());
        stat.add(String.valueOf(score));
        stat.add(b.getDeuxPointsReussis() + "/" + b.getDeuxPoints());
        stat.add(b.getTroisPointsReussis() + "/" + b.getTroisPoints());
        stat.add(b.getLancerFrancsReussis() + "/" + b.getLancerFrancs());
        stat.add(String.valueOf(b.getRebonds()));
        stat.add(String.valueOf(b.getPassesDecisives()));
        stat.add(String.valueOf(b.getFautes()));
        stat.add(String.valueOf(b.getInterceptions()));
        stat.add(String.valueOf(b.getBallonsPerdus()));
        stat.add(String.valueOf(b.getContres()));
        stat.add(String.valueOf(CalculStatistiquesService.getInstance().calculerEvaluation(b)));
        return stat;
    }

    public static GenerationTableauMatch getInstance() {
        return instance;
    }
}
INSERT INTO equipes(id, nom) 
VALUES 
	(1, 'Orléans'), 
	(2, 'Limoges');
INSERT INTO joueurs (id, nom, prenom, id_equipe)
VALUES 
	(201, 'CAMARA', 'Ousmane', 2),
	(202, 'JONES', 'Joseph', 2),
	(203, 'PREPELIC', 'Klemen', 2),
	(204, 'WOJCIECHOWSKI', 'Mathieu', 2),
	(205, 'WOOD', 'Dashaun', 2),
	(206, 'DELAGE', 'Benjamin', 2),
	(207, 'DUPORT', 'Romain', 2),
	(208, 'FAIR', 'C.J', 2),
	(209, 'MUNANGA', 'Shekinah', 2),
	(210, 'RANDLE', 'Jerome', 2),
	(211, 'ZERBO', 'Fréjus', 2),
	(101, 'DOWNS', 'Micah', 1),
	(102, 'LOUBAKI', 'Luc', 1),
	(103, 'MILOSEVIC', 'Nemanja', 1),
	(104, 'McALARNEY', 'Kyle', 1),
	(105, 'OLASENI', 'Gabe', 1),
	(106, 'JOSEPH', 'Georgi', 1),
	(107, 'MENDY', 'Antoine', 1),
	(108, 'PRINCE', 'John', 1),
	(109, 'SOMMERVILLE', 'Marcellus', 1),
	(110, 'SYLLA', 'Abdel Kader', 1),
	(111, 'VINCENT', 'Thomas', 1);
	
INSERT INTO matchs(id) VALUES (34);

INSERT INTO bilans (id_match, id_joueur, lancer_francs_reussis, lancer_francs, deux_points_reussis, deux_points, trois_points_reussis, trois_points, rebonds, fautes, passes_decisives,ballons_perdus, interceptions, contres)
VALUES 
	(34, 201, 0, 0, 6, 14, 0, 0, 8, 3, 1, 1, 0, 0),
	(34, 202, 0, 1, 2, 3, 0, 0, 0, 2, 1, 1, 0, 0),
	(34, 203, 4, 4, 0, 3, 3, 9, 1, 4, 5, 1, 0, 0),
	(34, 204, 0, 0, 0, 0, 2, 2, 8, 4, 2, 1, 0, 0),
	(34, 205, 0, 0, 2, 4, 1, 7, 2, 3, 2, 3, 3, 0),
	(34, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
	(34, 207, 0, 0, 1, 3, 1, 3, 2, 0, 0, 0, 0, 0),
	(34, 208, 2, 4, 3, 4, 0, 3, 5, 1, 0, 0, 1, 1),
	(34, 209, 0, 0, 2, 3, 1, 1, 3, 2, 0, 1, 1, 0),
	(34, 210, 0, 0, 4, 7, 2, 4, 1, 0, 3, 4, 0, 0),
	(34, 211, 3, 4, 1, 3, 0, 0, 1, 0, 0, 0, 1, 0),
	(34, 101, 1, 2, 2, 2, 3, 5, 5, 0, 4, 1, 0, 0),
	(34, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0),
	(34, 103, 0, 0, 2, 2, 1, 2, 1, 1, 1, 0, 0, 0),
	(34, 104, 3, 3, 0, 2, 1, 4, 3, 1, 2, 1, 1, 0),
	(34, 105, 2, 2, 4, 10, 0, 0, 6, 2, 2, 0, 1, 0),
	(34, 106, 0, 0, 1, 1, 1, 1, 3, 2, 1, 1, 1, 0),
	(34, 107, 1, 1, 5, 7, 2, 7, 3, 0, 2, 1, 1, 0),
	(34, 108, 1, 2, 7, 8, 1, 2, 5, 2, 10, 2, 4, 0),
	(34, 109, 4, 4, 4, 6, 0, 1, 3, 3, 3, 2, 0, 0),
	(34, 110, 0, 1, 5, 7, 0, 0, 5, 2, 4, 2, 2, 0),
	(34, 111, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0);
public class GenerationTableauMatchTest {

    private Connection cnx;

    @Before
    public void setUp() {
        JdbcDataSource dataSource = new JdbcDataSource();
        dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
        dataSource.setUser("sa");
        dataSource.setPassword("");
        try {
            cnx = dataSource.getConnection();
            try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
                RunScript.execute(cnx, br);
            }
            try (InputStreamReader fr = new FileReader(new File("src/test/resources/data/GenerationTableauMatchTest.sql")); BufferedReader br = new BufferedReader(fr)) {
                RunScript.execute(cnx, br);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    @After
    public void tearDown() {
        try {
            cnx.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testerGenerationTableaux() {
        try {
            TableauMatch t = GenerationTableauMatch.getInstance().genererTableauMatch(cnx, 34);
            Assert.assertEquals(true, t.getTableauEquipe1() != null);
            Assert.assertEquals(true, t.getTableauEquipe2() != null);
            Assert.assertEquals("Limoges", t.getTableauEquipe1().getNomEquipe());
            Assert.assertEquals(11, t.getTableauEquipe1().getStatistiques().size());
            int cpt = 0;
            Assert.assertEquals("Ousmane CAMARA", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("12", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("6/14", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("0/0", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("0/0", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("8", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("1", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("3", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("0", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("1", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("0", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("12", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
        }
        catch (Exception e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
}

Bilan

Nous avons testé notre application de manière méticuleuse et sans trop en faire, malgré tout, le refactoring et l'adaptation de l'application à nos test a été une part importante du travail de test, sans doute l'étape la plus longue et complexe

Les sources de la solution sont disponnibles ici : projet basket : solution, le pom utilisé est le suivant : projet basket : solution

La couverture de test est de 55,7% ce qui est un bon score mais encore loin des 80% recommandés. La question la plus importante à se poser n'est pas "quel est ma couverture de test ?" mais "est-ce que je couvre une partie suffisante des fonctionnalités de l'application ?" et dans notre cas, nous ne pouvons pas réelement faire mieux sans tester des choses triviales ou sans dégrader la simplicité de nos tests

Couverture de test