How to setup MongoDB for integration tests in NodeJS?
Asked Answered
A

3

9

I am writing integration tests for application written in NodeJS with MongoDB.

On CI server I would like to have some sort of embedded MongoDB for faster performance and easier control. Currently I have MongoDB on other server, but tests are slow. Before each test I need to drop all collections. I am using mongoose as ORM.

So far I have only found embedded MongoDB for Java.

Assuntaassur answered 27/6, 2013 at 11:38 Comment(1)
You could just set up a dedicated MongoDB instance on your CI server...Tuition
S
6

As of this writing, I'd recommend using mongodb-memory-server. The package downloads a mongod binary to your home directory and instantiates a new memory-backed MondoDB instance as needed. This should work well for your CI setup because you can spin up a new server for each set of tests, which means you can run them in parallel.

See the documentation for details on how to use it with mongoose.


For readers using jest and the native mongodb driver, you may find this class useful:

const { MongoClient } = require('mongodb');
const { MongoMemoryServer } = require('mongodb-memory-server');

// Extend the default timeout so MongoDB binaries can download
jest.setTimeout(60000);

// List your collection names here
const COLLECTIONS = [];

class DBManager {
  constructor() {
    this.db = null;
    this.server = new MongoMemoryServer();
    this.connection = null;
  }

  async start() {
    const url = await this.server.getUri();
    this.connection = await MongoClient.connect(url, { useNewUrlParser: true });
    this.db = this.connection.db(await this.server.getDbName());
  }

  stop() {
    this.connection.close();
    return this.server.stop();
  }

  cleanup() {
    return Promise.all(COLLECTIONS.map(c => this.db.collection(c).remove({})));
  }
}

module.exports = DBManager;

Then in each test file you can do the following:

const dbman = new DBManager();

afterAll(() => dbman.stop());
beforeAll(() => dbman.start());
afterEach(() => dbman.cleanup());
Shredding answered 3/8, 2018 at 17:43 Comment(1)
Great example. This approach should be used in the official Jest docs. Good luck following their "one instance" mongodb example with Jest's concurrencyOwens
A
1

Following the "don’t use test doubles for types you don’t own" principle, consider continue using a real MongoDB instance for your integration test. Look at this nice article for details.

Allerie answered 27/9, 2014 at 6:0 Comment(0)
L
0

Our team has been stubbing out the mongo skin calls. Depending on your testing packages you can do the same thing. It takes a little bit of work but it is worth it. Create a stub function and then just declare what you need in your test.

   // Object based stubbing
    function createObjStub(obj) {
      return {
        getDb: function() {
         return {
            collection: function() {
              var coll = {};

              for (var name in obj) {
                var func = obj[name];

                if (typeof func === 'object') {
                  coll = func;
                } else {
                  coll[name] = func;
                }
              }

              return coll;
            }
          };
        }
      }
   }; 
    // Stubbed mongodb call
      var moduleSvc = new ModulesService(createObjStub({
        findById: function(query, options, cb) {
          return cb({
             'name': 'test'
           }, null);
           //return cb(null, null);
        }
      }),{getProperties: function(){return{get: function(){} }; } });
Lysias answered 27/6, 2013 at 13:27 Comment(1)
This is one way it can be done, but I will cut all the MongoDB checks, constraints and processes. If there is primary key that is unique, second write will not return error. If there is wrong saving of information, wrong query or wrong initialization, I will not notice that.Bracci

© 2022 - 2024 — McMap. All rights reserved.