Tester unitairement ses DAO MongoDB

mongodb-nosql-logo

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 :

Download mongo

Ç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.

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.