Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking MongoDB connection for MEAN application unit testing

I've been wracking my brains trying to figure out a way to handle mocking my MongoDB connection for my unit tests. I'm wondering what the proper method is for doing this since my application layout may be the issue. This is for a larger project with lots of modules.

The general layout

 package.json
 server.js
-models
    -index.js
    -users.js
    -events.js
    -...
-services
    -index.js
    -userActivity.js
    -...
 +public
+routes
+util
+test

models/users.js

"use strict";
modules.export = function(mongoose) {
  var Schema = mongoose.Schema;
  var userSchema = new Schema({ name: String });
  var userModel = mongoose.model('User', userSchema);
  var userDAO {};

  userDAO.addUser(user) {
    var newUser = new userModel(user);
    return newUser.save();
  }

  userDAO.getUser(id) {
    return userModel.findById(id).lean().exec();
  }

  return userDAO;
};

models/index.js

"use strict";
var bluebird= require('bluebird');
var mongoose = bluebird.promisifyAll(require('mongoose'));

var Users = require ('./users');
var Events = require('./events');

module.exports.Users = new Users(mongoose);
module.exports.Events = new Events(mongoose);

services/userActivity.js

"use strict";
var db = require('../models');

module.exports = function(userID) {
  return db.Events.getEventsForUser(userId)
};

Now here's where the problem is

test/test.js

"use strict";
var chai = require('chai');
chai.use(require('chai-as-promised');
var expect = chai.expect;

var mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/testDB")

var db = require('../models');
var services = require('../services')

describe("sample tests", function() {
  var user1, user2;
  var user1TestEvents = [];    

  before(function(done) {
    db.Users.addUser({name:"John"}).
    then(function(john) {
      user1 = john;
      return db.Users.addUser({name: "Mary"});
    }).
    then(function(mary) {
      user2 = mary;
      return db.Events.addEvent{user: user1._id, event: "logged in", time: new Date()});
    }).
    then(function(event) {
     user1TestEvents.push(event);
     done()
    });
  };

  it('gets a users events', function() {
    var events = services.getEventsForUser(user1._id);
    return expect(events).eventually.to.have.length(user1TestEvents.length);
  });

The tests work just fine if I connect to a live database on my own machine, but our CI servers won't have a mongo database running on them. I have been trying to figure out some way of faking the connection but I haven't found any good alternatives

I have been trying to use Mockgoose to get mock the database but unless I pass the mockgooesed mongoose object all the way down through all the components it will not work.

var mockgoose = require('mockgoose');
var mongoose = require('mongoose');
mockgoose(mongoose);

mongoose.connect("mongodb://localhost/test");

When I tried this, after the first promise resolves in my "before", all subsequent promises never resolve and mocha times out.

I haven't been able to get tingoDB working either and I'm feeling like I'm missing something obvious.

All of the examples I've seen were very simple test cases where the models were created in the same location that the mongoose object performed the connection and with the way I have the application broken apart I can't seem to get a decoupling from mongoose to the actual MongoDB instance.

If anyone has experience with unit testing MEAN applications without an actual MongoDB instance I'd be very happy for some advice on how to fix my layout and get my unit tests working.

like image 657
Ilvenis Avatar asked Jun 17 '15 21:06

Ilvenis


People also ask

Can database be mocked for unit testing?

Yes, absolutely! Because our code that talks to the real DB is already tested carefully in the previous lecture. So all we need to do is: make sure that the mock DB implements the same interface as the real DB. Then everything will be working just fine when being put together.

What does mocking mean in unit testing?

Mocking means creating a fake version of an external or internal service that can stand in for the real one, helping your tests run more quickly and more reliably.


1 Answers

You can use rewire to mock any module you require. And redefining the method you need.

like image 146
Sachacr Avatar answered Sep 16 '22 13:09

Sachacr