Open In App

How to use mocha with mongoose ?

Improve
Improve
Like Article
Like
Save
Share
Report

Mocha: Mocha is a testing framework that is used to perform tests within our application.It makes sure everything works correctly.

‘Mocha in Node.js’ means using the mocha unit testing framework in Node.js runtime environment. Mocha has tons of great features.

Key Features:

  • Simple async support.
  • Async test timeout support.
  • Use any assertion library you want
  • Before, after, before each, after each hooks are very useful to clean the environment with each test.

If you are not familiar with mongoose, click here.

Throughout some stretch of time, our application will have a greater number of lines of code for testing than the real application rationale. So it’s consistently something to be thankful for to compose tests and follow a Test Driven Development or TDD approach.

In this post, we will set up a fundamental testing suite to make our Create Read Update and Delete (CRUD) procedure on the MongoDB data set with the Mongoose library utilizing the most well-known Mocha testing structure.

Installing Modules:

npm i mocha mongoose

Folder structure: We’ll create all out test files in the test directory.

In our Node.js-MongoDB project, we’ll be using this helper file for creating connection. If you are new to MongoDB check this post.

test_helper.js




// test/test_helper.js
  
const mongoose = require('mongoose');
  
// tells mongoose to use ES6 implementation of promises
mongoose.Promise = global.Promise;
const MONGODB_URI = 'mongodb://mongodb0.example.com:27017';
mongoose.connect(MONGODB_URI);
  
mongoose.connection
    .once('open', () => console.log('Connected!'))
    .on('error', (error) => {
        console.warn('Error : ', error);
    });
      
    // runs before each test
    beforeEach((done) => {
        mongoose.connection.collections.users.drop(() => {
        done();
       });
});


We’ll be using the beforeEach() hook to empty our DB before our tests run. Deletion takes time, so we need to hold mocha before the operation finishes. Calling the done() function tells that the operation is finished now and we can continue the execution.

The .on() and .once() are the event handlers. They take the event as the first argument and a function as the second argument which executes once the event occurs.

Our MongoDB Schema:

user.js




// Inside schema/user.js
  
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
  
const UserSchema = new Schema({
    name: {
        type: String,
        required: [true, 'Name is required.']
      },
    age: Integer
 })
   
// it represents the entire collection of User data
const User = mongoose.model('User', UserSchema);
module.exports = User;


Now, we need a script in our package.json file to start the test.

"scripts": { 
  "test" : "mocha --recursive --exit"
 }

In –recursive means it will recursively test inside the test directory and –exit to exit whenever all tests have been executed. Use the following command to run tests using Mocha.

npm run test

Mocha provides us a describe() function which takes a string as the first parameter which is used to identify the group of tests that are passing or failing, and the testing logic is implemented as a function in the second parameter of describe().

The describe() may contain multiple tests inside an it() method or nested describe() functions as well. In our case, we will be making different files for each CRUD operation in MongoDB. Alternatively, we could have used a single file with different describe blocks.

As every test needs us to assert something, Mocha allows us to use many assertion libraries. Here we’ll be using Node.js’ built-in assert module. 

By adding done() to it() in a test callback, Mocha will know that this test has been completed.
 

create_test.js




//import the User model
const User = require('../schema/user');
const assert = require('assert');
  
describe('Creating documents in MongoDB', () => {
    it('Creates a New User', (done) => {
        const newUser = new User({ name: 'Shriyam' });
        newUser.save() // returns a promise after some time
            .then(() => {
                //if the newUser is saved in db and it is not new
                assert(!newUser.isNew);
                done();
            });
    });
});


read_test.js




const User = require('../schema/user');
const assert = require('assert');
  
let user;
// this will run before running every test
beforeEach(() => {
    // Creating a new Instance of User Model
    user = new User({  name: 'Shriyam' });
    user.save()
        .then(() => done());
});
  
describe('Reading Details of User', () => {
    it('Finds user with the name', (done) => {
        User.findOne({ name: 'Shriyam' })
            .then((user) => {
                assert(user.name === 'Shriyam');
                done();
            });
    })
})


delete_test.js




const User = require('../schema/user');
const assert = require('assert');
  
describe('Deleting a User', () => {
  
    let user;
    beforeEach((done), () => {
        // user is an instance of User Model
        user = new User({ name: 'Shriyam' });
        user.save()
            .then(() => done());
    });
  
    it('Removes a User using its instance', (done) => {
    User.remove()
        // Checking if the user was deleted from DB or not
        .then(() => User.findOne({ name: 'Shriyam' }))
        .then((user) => {
            assert(user === null);
            done();
        });
    });
  
    it('Removes a user', (done) => {
    User.findOneAndRemove({ name: 'Shriyam' })
        .then(() => User.findOne({ name: 'Shriyam' }))
        .then((user) => {
            assert(user === null);
            done();
        });
    });
  
    it('Removes a user using its id', (done) => {
    User.findIdAndRemove(user._id)
        .then(() => User.findOne({ name: 'Shriyam' }))
        .then((user) => {
            assert(user === null);
            done();
        });
    })
})


update_test.js




const Username = require('../schema/user');
const assert = require('assert');
  
describe('Deleting a user', () => {
  
    let user;
    beforeEach((done) => {
        user = new User({ name: 'Shriyam' });
        user.save()
            .then(() => done());
    });
  
    // Handling Redundant Code
    function helperFunc(assertion, done) {
    assertion
        .then(() => User.find({}))
        .then((users) => {
            assert(users.length === 1);
            assert(users[0].name === 'Updated Shriyam');
            done();
        });
    }
  
    it('Sets and saves a user using an instance', (done) => {
        // Not yet updated in MongoDb
        user.set('name', 'Updated Shriyam');
        helperFunc(user.save(), done);
    });
  
    it('Update a user using instance', (done) => {
        helperFunc(user.update({ name: 'Updated Shriyam' }), done);
    });
});


So, we have now learned how to create Unit Tests using Mocha with Mongoose.
Tip: Use mockgoose library to use a Dummy MongoDB Database so that your original DB stays clean.



Last Updated : 14 Apr, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads