Testing NodeJs code with Expect/Supertest

Categories NodeJs, Start Coding, Typescript, Unit Testing
Testing
In this blog post I´m going to show you how to test NodeJs code with the Third Party Modules `expect` and `supertest` and `mocha` asynchronous calls. No worries if you are new to javascript, I´m too but I enjoy learning all area´s of javascript so far. Recently I wrote a article about Promises in Javascript

Excpect

Expect is an Assertion Library which makes testing values much more easy. Let´s move on with installing this module with NPM

NPM_excpect_module Example:
describe('generateMessage', () => {
    it('should generate correct message object', function () {
        var from = 'Modev';
        var text= 'Test text';
        var res = generateMessage( from, text );

        expect( res.from ).toBe( from );          // Test if "res.from" has the same value as "from"
        expect( res.text ).toBe( text )           // Test if "res.text" has the same value as "text"
        expect( res.createdAt).toBeA( 'number' ); // Test if "createdAT" is type of 'number'

    });
});
The describe block creates a test environment. The it blocks defines test cases which need to pass. Reading it out loud sounds rather fine. Describe generateMessage(), it should generate correct message object.

Supertest

The motivation with this module is to provide a high-level abstraction for testing HTTP, while still allowing you to drop down to the lower-level API provided by superagent.

NPM_supertest_module Example:
const { app } = require('./../server');
const request = require('supertest'); // Include Supertest
const expect = require('expect');     // Include Expect

describe('PATCH /todos/:id', () => {
    it('should updated a todo ',  ( done ) => {
        // ID from MongoDB
        var hexId = todos[0]._id.toHexString();
        // Text that is getting updated
        var text = "Updated text";

        // Calling supertest with request because I required it with the alias request
        // Variable app is from the server.js file which is also importet
        request(app)
            .patch(`/todos/${hexId}`)
            .send( {
                completed: true,
                text
            })
            .set('x-auth', users[0].tokens[0].token)
            .expect( 200 )
            .expect( ( res ) => {
                expect( res.body.todo.text ).toBe( text);
                expect( res.body.todo.completed).toBe( true );
                expect( res.body.todo.completedAt).toBeA( 'number' );
            })
            .end( done )
    });
Now I hope you got an overview about testing `HTTP` request with `supertest` and `excpect`. However there is asynchronous code going on you may wonder how to test this. For this there is a Framework called `Mocha` let´s take a look at this wonderful Javascript test framework.

Mocha

Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making `asynchronous ` testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. — mochajs.org

I actually used Mocha is aboved mentioned Code example for `supertest` because there is something asynchronous going on because of the callback function of the custom excpect call. If you don´t know what asynchronous operations are, no problem  I´ll guide you through in this article.
const expect = require('expect');
const request = require('supertest');
const { app } = require('./../server');

describe('POST /todos', () => { 
 it('should not create todo with invalid body data', ( done ) => {
        request(app)
            .post('/todos')
            .set('x-auth', users[0].tokens[0].token)
            .send({})
            .expect( 400 )
            .end( ( err, res ) => {
                if ( err ) {
                    return done( err );
                }

                Todo.find().then( ( todos ) => {
                    expect( todos.length ).toBe( 2 );
                    done();
                }).catch( ( err ) => done( err ) )
            })
    })
});
At the beginning of the file we need to require both `excpect` and `supertest` and the `app` variable form the server file to make http requests. The describe block creates a test environment. The it blocks defines test cases which need to pass. Reading it out loud sounds rather fine. Describe POST /todos(), it should not create todo with invalid body data. We must use call `done` to say the test that the asynchrnous operation is over. Can you now see why testing is important apart from making sure the code works? A test is in itself documentation. Writing a test will explain what the code does. Every other developer working on the code base will have no issue understanding it in no time. All that’s left is to run the tests. Add "test": "mocha" in the scripts section of your package.json and you’ll be ready to go!
Hint, your package.json should look like this:
{
  "name": "chat-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "mocha server/**/*.test.js", // THAT IS important
//    "test-watch": "nodemon --exec 'npm test'",
    "start": "node server/server.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/Rayleigh3105/node-chat-app.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/Rayleigh3105/node-chat-app/issues"
  },
  "homepage": "https://github.com/Rayleigh3105/node-chat-app#readme",
  "dependencies": {
    "express": "^4.14.0",
    "socket.io": "^1.4.8"
  },
  "devDependencies": {
    "expect": "^1.20.2",
    "mocha": "^3.0.2",
    "nodemon": "^1.10.2"
  }
}
This test script will run every file which ends with `test.js`. Jump back to your terminal window and run npm test. You’ll see an awesome interface with some green text saying there is 1 passing test! NPM_mocha

The End of the Storie

You now have an brief overview how to cover asynchronous code with tests. All the examples in this blog post have been showing unit tests, which is more thant enough to begin with. If you want to take a look at other testing article I wrote feel free to visit my blog.

Hope you guys and girls enjoyed reading this as much as I enjoyed writing it. Do you think this tutorial will be of help to someone? Do not hesitate to share. If you liked it, share it somewhere else or subscribe to my blog.

Greetings Moritz 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *