We would like to use integrations and unit tests that don't require an actual database. As of this writing there are several solutions to this problem with relational databases, however we are using Mongo, a popular NOSQL db.
We have found using embedmongo (https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo) useful for this task.
Here is a sample of how to make this work...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//STEP 1. Add the maven resource into your sbt file | |
object ApplicationBuild extends Build { | |
val appDependencies = Seq( | |
// ... | |
"de.flapdoodle.embed" % "de.flapdoodle.embed.mongo" % "1.36", | |
..... | |
) | |
val main = play.Project(appName, appVersion, appDependencies).settings( | |
.... | |
// include the maven repo local here... | |
resolvers += "maven repo" at "http://repo1.maven.org/maven2/", | |
.... | |
) | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package utils; | |
import java.io.IOException; | |
import com.mongodb.DB; | |
import com.mongodb.DBCollection; | |
import com.mongodb.Mongo; | |
import com.mongodb.MongoException.Network; | |
import de.flapdoodle.embed.mongo.MongodStarter; | |
import de.flapdoodle.embed.mongo.MongodExecutable; | |
import de.flapdoodle.embed.mongo.MongodProcess; | |
import de.flapdoodle.embed.mongo.config.IMongodConfig; | |
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder; | |
import de.flapdoodle.embed.mongo.config.Net; | |
import de.flapdoodle.embed.mongo.distribution.Version; | |
/** | |
* Used to start and stop the embedded Mongo server, specifically for testing | |
* @author codynet | |
* | |
*/ | |
public class EmbedMongoHelper { | |
private static MongodProcess mongod; | |
private static MongodExecutable mongodExecutable; | |
/** | |
* Starts the Mongo Process | |
* @param port - Standard port for mongo is 27017 | |
* @throws IOException | |
*/ | |
public static void StartEmbeddedMongo(int port) throws IOException { | |
//check if mongo is already running | |
if(mongod!=null && mongod.isProcessRunning()) return; | |
IMongodConfig mongodConfig = new MongodConfigBuilder() | |
.version(Version.Main.PRODUCTION).net(new Net(port, true)) | |
.build(); | |
MongodStarter runtime = MongodStarter.getDefaultInstance(); | |
MongodExecutable mongodExecutable = null; | |
mongodExecutable = runtime.prepare(mongodConfig); | |
mongod = mongodExecutable.start(); | |
} | |
/** | |
* Stopper for Embedded Mongo Process | |
*/ | |
public static void StopEmbeddedMongo() { | |
if (mongodExecutable != null) | |
mongodExecutable.stop(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import org.junit.After; | |
import org.junit.Before; | |
import org.junit.Test; | |
import org.junit.runner.RunWith; | |
import utils.EmbedMongoHelper; | |
public class MyIntegrationOrUnitTest { | |
@Before | |
public void setUp() throws IOException { | |
EmbedMongoHelper.StartEmbeddedMongo(27017); | |
//other setup stuff | |
} | |
@Test | |
public void someTest1() { | |
//.... | |
//assertSome things | |
} | |
@Test | |
public void someTest2() { | |
//.... | |
//assertSome things | |
} | |
@After | |
public void tearDown() { | |
//.... | |
EmbedMongoHelper.StopEmbeddedMongo(); | |
} | |
} |
The above describes the quick and dirty steps for starting up the embedded Mongo instance in an integration test.
In practice, I have created an EmbeddedMongo class with a startup and teardown method which makes use of the play framework properties file to populate the appropriate port for testing and to encapsulate the private members mentioned above.