In this article, we shall set up a Nodejs project with TDD(Test Driven Development) using mocha (Test runner) and chai (Test Suite).

Let’s jump right in!

Initializing a new project

Create a new project directory called TDD and run npm init -y

mkdir TDD
cd TDD/
npm init -y 

npm init -y creates a Nodejs project with a package.json with all defaults filled out.

Add mocha and chai dev dependencies

Add mocha and chai development dependencies

npm install -D mocha chai

-D flag saves the two dependencies under devDependencies in a package.json file at the project root. Installation of the two dev dependencies creates a package-lock.json, a “cache” of the dependencies. This file is autogenerated and should not be edited.

Write our first test case

This won’t exactly be a test case but a dummy test case to get a glimpse of how to set up things.

  1. Create a source directory named src, as the convention. All our project source files will go here.
  2. Create a __test__ directory at the project root.
  3. Inside the __test__ directory, create a new file name index.spec.js, the .spec.js is a convention to differentiate the tests and regular project source.
  4. Inside src/ create an index.js file.
  5. Let’s add a dummy test case: Import chai dependency inside. We shall be using assert function to do the assertions. chai offers should and expect functions for doing more complex assertions
const { assert } = require('chai')
// more code here:

When using chai/mocha, we call describe function, pass in a description of the test and a callback function which is gets called by the mocha test runner.

const { assert } = require('chai')

describe('#Test square function', function()  {
  // test cases go here

} )
  1. Lets add a test case inside the describe callback function.
const { assert } = require('chai')

describe('#Test square function', function()  {
  // test cases go here
  it('squares a number and return a value', function() => {
    const sq = square(4)
    assert(sq === 16, "squar of 4 is 16")
} )
  1. Update the package.json under scripts, add a test script.
  // possible properties ommited
  "scripts" : {
    "test": "mocha"

Run the test:

npm test

The test fails because we don’t have the square function implementation yet.

  1. Let’s create a function that squares a number and returns the value.
const square = (num) => num ** 2

module.exports = square

Run the tests once more

npm test

The test passes.

mocha runs any test files under the test directory

Mocha and Chai make testing async and Promises much easier. Let’s explore more

Async and Promises

Let’s add a function that times out after 6000ms to mimic a delay as in an HTTP request inside src/index.js

const fetchAuth = () => {
  return new Promise((reject, resolve) => {
    setTimeout(() => {
      const data = JSON.stringify({auth: true: token: 'e66d515e-6cbe-46d0-9f22-8705a17b5b6d'})
    }, 6000)

module.exports = fetchHeroes
  1. Add a new test case. One may have a single describe or many describe functions within every single file.
describe('', function() {
  it('Fecthes auth and an token', async function() {
    const data = await fetchAuth()
    const auth = JSON.parse(data)
    assert(auth.auth === true, "auth property is true")
    assert(typeof(data.token) === 'string')


Mocha and Chai provide a way to write and run unit tests. Mocha is the test runner while chai is the test suite providing:

  • expect
  • should
  • assert functions to perform assertions

To learn more about Mocha and Chai, check out their docs: and