
Nous allons voir aujourd'hui comment tester unitairement les DAO accédant à une base MongoDB grâce à la librairie de.flapdoodle.embed.mongo. Cette dernière permet de télécharger et démarrer à la volée un serveur Mongo qui nous servira pour nos tests unitaires.
Commençons tout d'abord par les dépendances :
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.netapsys</groupId>
<artifactId>blog</artifactId>
<version>1.0.0</version>
<properties>
<mongo-java-driver-version>2.12.2</mongo-java-driver-version>
<embed-mongo-version>1.46.0</embed-mongo-version>
<junit-version>4.12</junit-version>
<jdk-level>1.7</jdk-level>
<maven-compiler-plugin-version>3.1</maven-compiler-plugin-version>
</properties>
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongo-java-driver-version}</version>
</dependency>
<!-- Dépendances de test -->
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>${embed-mongo-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin-version}</version>
<inherited>true</inherited>
<configuration>
<source>${jdk-level}</source>
<target>${jdk-level}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
pom.xml
Vous pourrez ensuite créer une super classe pour vos tests :
package com.netapsys.blog.dao;
import java.io.IOException;
import java.net.UnknownHostException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodProcess;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.MongoCmdOptionsBuilder;
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.distribution.Version;
/**
* Classe abstraite utilisée pour les tests des DAO
* @author ssenouci
*
*/
public abstract class AbstractMongoDbTest {
/**
* Instance du process mongod
*/
private static MongodProcess mongodProcess;
/**
* Instance de l'exécutable
*/
private static MongodExecutable mongodExecutable;
private static final String IP = "127.0.0.1";
private static final int PORT = 27017;
private static final String DB_NAME = "blog";
/**
* Initialise l'exécutable et le process mongod avant l'exécution des tests
* @throws IOException
*/
@BeforeClass
public static void beforeClass() throws IOException {
MongodStarter starter = MongodStarter.getDefaultInstance();
IMongodConfig mongodConfig = new MongodConfigBuilder()
.version(Version.Main.PRODUCTION)
.net(new Net(IP, PORT, false))
.cmdOptions(new MongoCmdOptionsBuilder()
.useSmallFiles(true)
.useNoJournal(true)
.useNoPrealloc(true)
.build()).build();
System.out.println("Récupération de l'exécutable");
mongodExecutable = starter.prepare(mongodConfig);
System.out.println("Lancement à la volée du serveur MongoDB");
mongodProcess = mongodExecutable.start();
System.out.println("Serveur MongoDB lancé avec succès");
}
/**
* Drop la base à la suite de chaque test
* @throws Exception
*/
@After
public void after() throws Exception{
System.out.println("Fin du test. Suppression de la base " + DB_NAME);
MongoClient client = new MongoClient(IP, PORT);
DB db = client.getDB(DB_NAME);
db.dropDatabase();
client.close();
System.out.println("Base " + DB_NAME + " supprimée avec succès");
}
/**
* Stop l'exécutable et le process mongod après l'exécution des tests
* @throws UnknownHostException
*/
@AfterClass
public static void destroyMongodInstance() throws UnknownHostException {
System.out.println("Arrêt du serveur MongoDB");
if (mongodProcess != null) {
mongodProcess.stop();
}
System.out.println("Arrêt de l'exécutable");
if (mongodExecutable != null) {
mongodExecutable.stop();
}
System.out.println("Fin des tests");
}
}
Super-classe des tests
Petite astuce pour ceux qui sont sur Windows, l'IP à utiliser lors du démarrage de la base Mongo doit être 127.0.0.1 (et non localhost), sinon un avertissement de sécurité apparaîtra à chaque lancement.
Vous disposez à présent des éléments nécessaires à l'élaboration de vos tests.
Prenons un exemple simple avec le DAO suivant :
package com.netapsys.blog.dao.personne;
import java.net.UnknownHostException;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.WriteResult;
/**
* DAO de la collection "personnes".
* @author ssenouci
*
*/
public class PersonneDao {
private DBCollection collection;
private final MongoClient mongoClient;
private final DB db;
public PersonneDao() throws UnknownHostException {
this.mongoClient = new MongoClient("localhost", 27017);
this.db = mongoClient.getDB("blog");
this.collection = this.db.getCollection("personnes");
}
/**
* Recherche une personne
* @return
*/
public DBObject findOne() {
return this.collection.findOne();
}
/**
* Insère une personne
* @param personne
* @return
*/
public WriteResult insert(DBObject personne) {
return this.collection.insert(personne);
}
}
PersonneDao
Nous souhaitons tester la méthode insert(DBObject personne). Cela peut désormais se faire via la classe de test suivante :
package com.netapsys.blog.dao.personne;
import java.net.UnknownHostException;
import org.junit.Assert;
import org.junit.Test;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.netapsys.blog.dao.AbstractMongoDbTest;
/**
* Classe de test de PersonneDao
* @author ssenouci
*
*/
public class PersonneDaoTest extends AbstractMongoDbTest {
/**
* Teste la création d'une personne
* @throws UnknownHostException
*/
@Test
public void testCreate() throws UnknownHostException {
PersonneDao personneDao = new PersonneDao();
Assert.assertNull(personneDao.findOne());
DBObject personne = new BasicDBObject("prenom", "Jean").append("nom", "Dupuis");
personneDao.insert(personne);
Assert.assertNotNull(personneDao.findOne());
}
}
PersonneDaoTest
Au premier lancement du test, la version de Mongo que vous avez spécifié devrait être téléchargée sur votre poste :

Ça peut être un peu long, mais cette opération n'est effectuée que la première fois, car l'archive téléchargée est stockée dans votre home.
Le reste devrait rouler tout seul.