Tests d'intégration avec DBunit

13 Jul 2014

Lorsqu'il faut tester une appli avec une BDD, il peut être difficile de maintenir le contenu de la BDD et les tests. DBUnit fournit les éléments pour alimenter une base (un ensemble de table) avant l'exécution d'un test et son nettoyage après l'exécution du test. Voici les différentes étapes pour utiliser DBunit avec une base Oracle 10g

Dépendances maven

Le dépendance maven pour DBUnit est

<dependency>
    <groupId>org.dbunit</groupId>
    <artifactId>dbunit</artifactId>
    <version>2.4.9</version>
    <scope>test</scope>
</dependency>

Il faut aussi ajouter celle du driver JDBC.

Préparation de la classe de test

On ajoute dans la classe de test un attribut de type org.dbunit.IDatabaseTester ainsi qu'une méthode permettant de créer cet objet.

import oracle.jdbc.pool.OracleDataSource;

import org.dbunit.DataSourceDatabaseTester;
import org.dbunit.IDatabaseTester;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.ext.oracle.Oracle10DataTypeFactory;

public class MonTest
{
   /** L'objet DBUnit permettant les opérations de préparation et nettoyage d'environnement. */
   protected static IDatabaseTester s_DatabaseTester;

    /**
    * Initialise l'environnement pour les tests d'un service TP.
    */
   @BeforeClass
   public static void setUpBeforeClass() throws Exception
   {
      s_Properties = new Properties();
      s_Properties.load(new FileInputStream(REPERTOIRE_BASE_CONF + "configuration.properties"));

      s_DatabaseTester = createDatabaseTester();
   }

   /**
    * @return Le {@link IDatabaseTester}.
    */
   protected static IDatabaseTester createDatabaseTester() throws Exception
   {
      IDatabaseTester tester = null;
      OracleDataSource dataSource = null;

      String url = s_Properties.getProperty("dts.database.url");
      String username = s_Properties.getProperty("dts.database.username");
      String password = s_Properties.getProperty("dts.database.password");

      dataSource = new OracleDataSource();
      dataSource.setURL(url);
      dataSource.setUser(username);
      dataSource.setPassword(password);

      tester = new DataSourceDatabaseTester(dataSource, username)
      {
         @Override
         public IDatabaseConnection getConnection() throws Exception
         {
            IDatabaseConnection connection = super.getConnection();
            connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY,
               new Oracle10DataTypeFactory());
            return connection;
         }
      };

      return tester;
   }
}

Ici nous utilisons l'implémentation org.dbunit.DataSourceDatabaseTester permettant de créer un DatabaseTester à partir d'une DataSource. DBUnit fournit d'autres implémentations. On peut mettre ces infos dans une classe abstraire commune à tous les tests de notre application.

Utilisation

Pour alimenter la BDD, les données doivent se trouver dans un org.dbunit.dataset.IDataSet. DBUnit propose des classes permettant de créer un DataSet à partir de fichier de différents formats. * org.dbunit.dataset.xml.XmlDataSet pour un fichier au format XML. * org.dbunit.dataset.csv.CsvDataSet pour un fichier au format CSV. * org.dbunit.dataset.excel.XlsDataSet pour un fichier au format Excel.

Seul le format XML est détaillé ici. Voici un exemple de fichier XML :

<!DOCTYPE dataset SYSTEM "../../dataset.dtd">
<dataset>
    <table name="DCP">
        <column>DCP_ID</column>
        <column>CODE</column>
        <column>NOM</column>
        <row>
            <value>999999990</value>
            <value>DCP01</value>
            <value>DCP_01</value>
        </row>
        <row>
            <value>999999991</value>
            <value>DCP02</value>
            <value>DCP_02</value>
        </row>
        <row>
            <value>999999992</value>
            <value>DCPPL</value>
            <value>DCP_PL</value>
        </row>
    </table>

    <table name="AUTRE_TABLE">
    ...
    </table>
</dataset>

Il faut donc créé le DataSet puis le passer au DatabaseTester.

public class MonTest
{
...

   /** Les données à utiliser pour le test. */
   private IDataSet m_DataSet;

   /**
    * Initialise l'environnement
    */
   @Before
   public void setUp() throws Exception
   {
      m_DataSet = new XmlDataSet(new FileInputStream(REPERTOIRE_RESOURCE_TEST + "rejets.xml"));

      s_DatabaseTester.setDataSet(m_DataSet);
      s_DatabaseTester.setSetUpOperation(DatabaseOperation.REFRESH);
      s_DatabaseTester.onSetup();
   }

   /**
    * Nettoie l'environnement
    */
   @After
   public void tearDown() throws Exception
   {
      s_DatabaseTester.setTearDownOperation(DatabaseOperation.DELETE);
      s_DatabaseTester.onTearDown();
   }
}

Dans la méthode setUp, * nous initialisons un DataSet à partir d'un fichier XML. Ce DataSet est passé au DatabaseTester. * on fixe le type d'opération pour l'alimentation des données dans la BDD : ici nous utilisons l'opération REFRESH qui permet de modifier des entrées déjà existantes en base. Les entrées existantes en base mais non présente dans le dataset ne sont pas modifiées. * on appelle la méthode onSetup() pour insérer les données.

Dans la méthode tearDown, * on fixe le type d'opération pour la suppression des données en fin de test : ici nous utilions l'opération DELETE qui supprime les uniquement les données présentes dans le dataset. * on appelle la méthode onTearDown() pour nettoyage.

Les autres opérations sont décrites ici

Il reste ensuite à écrire les tests (appel du service + vérification)

Un projet exemple se trouve ici.