Testing with mocha.js

Mocha is a testing-framework. See GitHub (21.8k ⭐).

$ npm i mocha

The two main components are

  • πŸ“¦ describe which is a suite of tests (it)
  • πŸ› οΈ it which is a test

To run your tests

# run every test file inside a folder
$ npx mocha folder
# run some specific tests
$ npx mocha folder --grep "Some tests" # Some tests
$ npx mocha folder --grep "test.*" # test1, test2

In a nutshell, the syntax you will use is something like that

describe('Some tests', function() {
    // you can init variables here
    const x1 = {}
    
    it('test1', function () {
        // your test here
    });
    it('test2', function () {
        // your test here
    });
})

Inside your it blocks, you will use a testing framework


Basics

Some additional notes about the features that mocha has to offer.

General notes

describe('Some tests', function() {
    // you can nest another describe
    describe('Another bunch', function() {
    })

    // you can add pending test (=to do)
    it('name')
})

Hooks

These are functions that are run before/after one/every test.

describe('name', function() {
    // before all tests
    before('name', function () {});
    // before each test
    beforeEach('name', function () {});
    // after all tests
    after('name', function () {});
    // after each test
    afterEach('name', function () {});
})

Skip a test

It's better to use skip than to comment out the code.

describe.skip('name', function () {});
it.skip('name', function () {});
it('name', function () {
    // ex: call based on a condition... 
    this.skip();
});

Async tests

Use this to test Promises/async code.

describe('name', function() {
    it('name', function (done) {
        asyncCode().then(() => {
            done(); // test done
        });
    });
    // or
    it('name', async () => {
        await asyncCode()
    });

    // you can set a custom timeout for one test
    it('name', async () => {
        await asyncCode()
    }).timeout(5000); // 5 seconds
})

Assertions with assert

Node.js provides an assertion library called assert.js.

let assert = require('assert');

You can use better-assert for c-style asserts.

it('name', function () {
    // examples
    assert.equal(actual, expected);
    assert.ok(boolean);
    assert.fail();
});

Testing requests with chai-http

This is an extension of chai to deal with HTTP requests.

See GitHub (0.7k ⭐).

const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('../app');
chai.use(chaiHttp);

For reference, in express, app.js is something like that

const app = express();
module.exports = app;

Then, you can run a test like this

it('name', (done) => {
    chai.request(app).get('/').end((err, res) => {
        // your tests here
        done()
    });
});

// for other requests
xxx.post('URI').send(body) // post
xxx.patch('URI').send(body) // patch
xxx.delete('URI') // delete

It's worth noting that if you do this, then for EVERY test, chai will create an HTTP server, run the request, and close it. You may want to keep the server open for all your tests.

Keep the client open
describe('name', function() {
    // open connection
    const requester = chai.request(app).keepOpen();

    it('name', async () => {
        const res = await requester.post('/').send({});
        // your tests here
    });

    after('name', async function () {
        await requester.close()
    });
});
Login cookie

This is a follow-up of the dropdown to keep the client open.

// get it back and save it
const cookies = res.headers['set-cookie'];

// in every following request
requester.get('/').set('Cookie', cookies[0]);

Should.js

Chai support should.js BDD assertions.

// at the top
chai.should();

// inside a test
res.should.have.status(200);
res.body.should.be.a('array');
res.body.should.be.a('object');
res.body.length.should.be.eql(0);
res.body.should.have.a.lengthOf.at.least(2);
res.body.should.have.property('xxx');
res.should.have.header('yyy');
res.body.should.be.eql('zzz')

Expect.js

Chai support expect.js BDD assertions. See expect.js (2.1k ⭐).

// at the top
chai.expect();

// inside a test
expect(res).to.have.status(200);
expect(res).to.be.json;
expect(res).to.redirectTo("xxx");
expect(res).to.have.header('yyy');
expect(req).to.have.cookie('zzz');

πŸ‘» To-do πŸ‘»

Stuff that I found, but never read/used yet.