javiercbk / naive-mongo

A naive mongo db driver implementation that mocks a mongodb database.
MIT License
2 stars 0 forks source link

Usage w/ mongoose #1

Open dsdenes opened 6 years ago

dsdenes commented 6 years ago

Hi there, thanks for the lib, it's a great idea. I hate to run mongo servers for testing.

Have you succeed to use the library with mongoose?

Denes Pal

javiercbk commented 6 years ago

I'm actually using it with mongoose 5.0.17 (5.0.18 and 5.1.0 have huge bugs), I have more or less 150 unit test in my application that depend on this library.

Some aggregations won't work and some are buggy, that's why the aggregation support is limited. In spite of all this, many of my unit test run aggregations with no issue.

Here is what I do to inject the naive-mongo connection into mongoose

const uuidV4 = require('uuid/v4');
const _ = require('lodash');
const Promise = require('bluebird');
const fs = require('fs');
const path = require('path');
const mongodb = require('naive-mongo');
const mongoose = global.mongoose || require('mongoose');

const toModelName = file => _.upperFirst(_.camelCase(file));

const buildSchema = function () {
  const models = {};
  const schemas = {};
  // I read all my schema files synchronously avoiding the index.js file
  fs.readdirSync(realSchemaDir).filter(f => f !== 'index.js' && !isDirectory(f))
  .map(f => f.substring(0, f.length - 3))
  .forEach((f) => {
    schemas[toModelName(f)] = require(path.join(realSchemaDir, f));
  });
  Object.keys(schemas).forEach((modelName) => {
    const model = mongoose.model(modelName, schemas[modelName]);
    model.mongoose = mongoose;
    models[modelName] = model;
  });
  return new Promise((resolve) => {
    const randomDBName = uuidV4();
    // Generates a random db name
    mongodb.MongoClient.connect(`mongodb://some.nasty.fake.host:8080/${randomDBName}`, ((err, db) => {
      let closePromise;
      if (mongoose.connection instanceof mongoose.Connection) {
        // if this is a mongoose.Connection, we will override it with our custom connection
        closePromise = Promise.resolve();
      } else {
        // forces closing the last connection if necessary
        closePromise = new Promise((res) => { mongoose.connection.close(true, res); });
      }
      return closePromise.then(() => {
        mongoose.connection = db;
        // grab all of our models and replace the connection with our naive-mongo connection
        Object.keys(mongoose.models).forEach((k) => {
          mongoose.models[k].collection.conn = {
            db: db,
            base: {
              options: {
                debug: false,
              },
            },
          };
          mongoose.models[k].collection.onOpen();
        });
        // you can inject spies if you like
        // initializeSpies(models);
        resolve(models);
      });
    }));
  });
};

In a unit test you call the previous defined function, here is an example with mocha

describe('Testing naive-mongo', () => {
  let schema;
  beforeEach(async () => {
    const s = await buildSchema();
    schema = s;
  });

  it('Simple test', async () => {
    // assuming there is a User schema
    const userFromDB = await schema.User.findOne({email: 'myuser@someemail.com'});
    expect(userFromDB).to.exist;
  });
});