This package spins up a actual/real MongoDB Server programmatically from node for testing or mocking during development. By default it holds the data in memory. Fresh spinned up mongod process takes about 7Mb of memory. The server will allow you to connect your favorite ODM or client library to the MongoDB Server and run integration tests isolated from each other.
This package on first start downloads the latest MongoDB binaries and save it to ~/.mongodb-binaries folder. So first run may take a time. All further runs will fast, because use already downloaded binaries.
Every MongodbMemoryServer instance creates and starts fresh MongoDB server on some free port. You may start up several mongod simultaneously. When you terminate your script or call stop() MongoDB server(s) will be automatically shutdown.
Perfectly works with Travis CI without additional services and addons options in .travis.yml.
yarn add mongodb-memory-server --dev
OR
npm install mongodb-memory-server --save-dev
importMongodbMemoryServerfrom'mongodb-memory-server';constmongod=newMongodbMemoryServer();consturi=awaitmongod.getConnectionString();constport=awaitmongod.getPort();constdbPath=awaitmongod.getDbPath();constdbName=awaitmongod.getDbName();// some code// you may stop mongod manuallymongod.stop();// or it will be stopped automatically when you exit from scriptAll options are optional.
constmongod=newMongodbMemoryServer({instance: {port?: ?number,// by default choose any free portdbName?: string,// by default generate random dbNamedbPath?: string,// by default create in temp directorystorageEngine?: string,// by default `ephemeralForTest`debug?: boolean,// by default false},binary: {version?: string,// by default '3.4.4'downloadDir?: string,// by default %HOME/.mongodb-binariesplatform?: string,// by default os.platform()arch?: string,// by default os.arch()debug?: boolean,// by default false},debug?: boolean,// by default falseautoStart?: boolean,// by default true});Take a look at this test file.
importmongoosefrom'mongoose';importMongodbMemoryServerfrom'mongodb-memory-server';constmongoServer=newMongodbMemoryServer();mongoose.Promise=Promise;mongoServer.getConnectionString().then((mongoUri)=>{constmongooseOpts={// options for mongoose 4.11.3 and aboveautoReconnect: true,reconnectTries: Number.MAX_VALUE,reconnectInterval: 1000,useMongoClient: true,// remove this line if you use mongoose 5 and above};mongoose.connect(mongoUri,mongooseOpts);mongoose.connection.on('error',(e)=>{if(e.message.code==='ETIMEDOUT'){console.log(e);mongoose.connect(mongoUri,mongooseOpts);}console.log(e);});mongoose.connection.once('open',()=>{console.log(`MongoDB successfully connected to ${mongoUri}`);});});For additional information I recommend you to read this article Testing a GraphQL Server using Jest with Mongoose
importmongoosefrom'mongoose';importMongodbMemoryServerfrom'mongodb-memory-server';mongoose.Promise=Promise;constmongoServer1=newMongodbMemoryServer();constmongoServer2=newMongodbMemoryServer();// Firstly create connection objects, which you may import in other files and create mongoose models.// Connection to databases will be estimated later (after model creation).constconnections={conn1: mongoose.createConnection(),conn2: mongoose.createConnection(),conn3: mongoose.createConnection(),};constmongooseOpts={// options for mongoose 4.11.3 and above
promiseLibrary =Promise;
autoReconnect: true,reconnectTries: Number.MAX_VALUE,reconnectInterval: 1000,useMongoClient: true,// remove this line if you use mongoose 5 and above};mongoServer1.getConnectionString('server1_db1').then((mongoUri)=>{connections.conn1.open(mongoUri,mongooseOpts);connection.once('open',()=>{console.log(`MongoDB successfully connected to ${mongoUri}`);});});mongoServer1.getConnectionString('server1_db2').then((mongoUri)=>{connections.conn2.open(mongoUri,mongooseOpts);connection.once('open',()=>{console.log(`MongoDB successfully connected to ${mongoUri}`);});});mongoServer2.getConnectionString('server2_db').then((mongoUri)=>{connections.conn3.open(mongoUri,mongooseOpts);connection.once('open',()=>{console.log(`MongoDB successfully connected to ${mongoUri}`);});});exportdefaultconnections;// somewhere in other fileimport{Schema}from'mongoose';import{conn1,conn2,conn3}from'./file_above';constuserSchema=newSchema({name: String,});consttaskSchema=newSchema({userId: String,task: String,});exportdefault{User: conn1.model('user',userSchema),Task: conn2.model('task',taskSchema),UserOnServer2: conn3.model('user',userSchema),}Note: When you create mongoose connection manually, you should do:
importmongoosefrom'mongoose';constopts={useMongoClient: true};// remove this option if you use mongoose 5 and aboveconstconn=mongoose.createConnection();// just create connection instanceconstUser=conn.model('User',newmongoose.Schema({name: String}));// define modelconn.open(uri,opts);// open connection to database (NOT `connect` method!)With default connection:
importmongoosefrom'mongoose';constopts={useMongoClient: true};// remove this option if you use mongoose 5 and abovemongoose.connect(uri,opts);constUser=mongoose.model('User',newmongoose.Schema({name: String}));// define modelStart Mocha with --timeout 60000 cause first download of MongoDB binaries may take a time.
importmongoosefrom'mongoose';importMongodbMemoryServerfrom'mongodb-memory-server';letmongoServer;constopts={useMongoClient: true};// remove this option if you use mongoose 5 and abovebefore((done)=>{mongoServer=newMongodbMemoryServer();mongoServer.getConnectionString().then((mongoUri)=>{returnmongoose.connect(mongoUri,opts,(err)=>{if(err)done(err);});}).then(()=>done());});after(()=>{mongoose.disconnect();mongoServer.stop();});describe('...',()=>{it("...",async()=>{constUser=mongoose.model('User',newmongoose.Schema({name: String}));constcnt=awaitUser.count();expect(cnt).to.equal(0);});});importmongoosefrom'mongoose';importMongodbMemoryServerfrom'mongodb-memory-server';// May require additional time for downloading MongoDB binariesjasmine.DEFAULT_TIMEOUT_INTERVAL=60000;letmongoServer;constopts={useMongoClient: true};// remove this option if you use mongoose 5 and abovebeforeAll(async()=>{mongoServer=newMongodbMemoryServer();constmongoUri=awaitmongoServer.getConnectionString();awaitmongoose.connect(mongoUri,opts,(err)=>{if(err)console.error(err);});});afterAll(()=>{mongoose.disconnect();mongoServer.stop();});describe('...',()=>{it("...",async()=>{constUser=mongoose.model('User',newmongoose.Schema({name: String}));constcnt=awaitUser.count();expect(cnt).toEqual(0);});});Additional examples of Jest tests:
- simple example with
mongodbin tests in current package - more complex example with
mongoosein graphql-compose-mongoose
For AVA written detailed tutorial how to test mongoose models by @zellwk.
You may cache downloaded MongoDB binaries on Travis to speed up further tests:
cache:
directories:
- $HOME/.mongodb-binariesAlso it is very important to limit spawned number of Jest workers for avoiding race condition. Cause Jest spawn huge amount of workers for every node environment on same machine. More details
Use --maxWorkers 4 or --runInBand option.
script:
- - yarn run coverage+ - yarn run coverage -- --maxWorkers 4Inspired by alternative runners for mongodb-prebuilt:
MIT