Javascript Testing with Mocha (Everything You Need To Know)

An introduction to the well known javascript testing framework

Jay's Notebook
4 min readJul 22, 2022
Photo by Michael Dziedzic on Unsplash

Introduction

Mocha is a feature-rich JavaScript test framework running on Node.js. Mocha tests run serially & asynchronously, allowing for flexible and accurate reporting while mapping uncaught exceptions to the correct test cases.

Quick Start

Mocha is installed with npm either globally or as a developer dependency within a project:

#global install
npm install --global mocha
#dependency install
npm install --save-dev mocha

Next, setup the project configuration for testing with mocha:

"script": { "test": "mocha" }

Finally, run tests in the terminal:

npm test

Assertions

Mocha isn’t opinionated on assertions; it can work seamlessly with any assertion library. For basic functionality, Node.js has an assert module that can be used. For a more extensive option, however, libraries like Chai can be used.

Interfaces

Mocha’s interface system allows developers to choose their style of DSL (Domain-Specific Language). The main two are BDD (Behaviour-Driven Development) and TDD (Test-Driven Development).

📍Notice: Moving forward, focus will be on the BDD style.

The BDD interface provides:

  • describe(), context(), it(), specify(), before(), after(), beforeEach(), afterEach().

The TDD interface provides:

  • suite(), test(), suiteSetup(), suiteTeardown(), setup(), teardown().

Test Suites

Test suites are a collection of test cases that are intended to prove a program’s specified behaviour.

The test suite’s structure in Mocha is defined by the hierarchical use of describe() > context() > it() > specify().

⚠️ Warning: Using lambdas may result in unexpected errors.

  • describe(description, function() {…}) is the test suite’s entry point.
  • context(context, function() {…}) is an alias of describe() and behaves the same way; it provides an extra level of organization.
  • it(case, function() {…}) is a test case with logic & assertion.
  • specify(case, function() {…}) is an alias of it() and behaves the same way; it provides an extra level of organization.

Here is a basic test suite for an array:

Hooks

Hooks are used to execute code before and after a test. They bind to the encompassing scope and execute their logic at that level. With its default BDD style interface, Mocha provides 4 hooks: before(), after(), beforeEach(), & afterEach().

✏️ Note: Hooks have the option of adding a label as their first argument

  • before(function() {…}) runs once before the first test in the collection.
  • after(function() {…}) runs once after the last test in the collection.
  • beforeEach(function() {…}) runs before each test in the collection.
  • afterEach(function() {…}) runs after each test in the collection.

Hooks define at the top scope of a test file are root hooks. These hooks execute their code on the broader scope of the implicitly created root suite.

Asynchrony

Mocha supports asynchrony with callback functions, Promises, & Async / Await.

Callback Functions

By adding an argument to the test case function it(), Mocha will know that it should wait for a callback to complete the test. This callback accepts both an Error instance or a falsy value; anything else is invalid usage and throws an error.

Here is an asynchronous callback function:

Promises

Alternatively, Promise objects may also be used. Simply return a promise that either resolves or rejects, and Mocha will handle the rest.

Here is an asynchronous promise function:

Async / Await

Finally, async / await can be used to turn a function into an asynchronous function.

Here is an asynchronous function using async & await:

Inclusive & Exclusive

Mocha supports modifying testing members with inclusive & exclusive runtime instructions. These instructions take the form of only() & skip().

  • only(description, function() {…}) excludes all test members of the same scope that are not similarly marked for inclusion.
  • skip(description, function() {…}) excludes self and all test members encapsulated within its scope.

Here is a test suite using both only() & skip():

Direct invocation of this.skip() is supported, allowing for a conditional assessment to be execute beforehand.

Here is a conditional statement to skip a test:

Retry Test

Mocha supports retrying tests that have failed. This is a feature designed to handle end-to-end tests where resources cannot be easily mocked.

The retries(retryCount) function (accessed through this) will retry a test if an assertion is thrown. This will be inherited by all nested members that do not override the value.

Here is an example use-case of retrying:

Timeouts

Mocha supports timeouts for all testing members.

The timeout(milliseconds) function (accessed through this) will timeout a test if it takes too long. This will be inherited by all nested members that do not override the value.

Here is a test that will timeout if it takes too long:

And That’s It!

As I’ve said on my page, these are notes from my own personal notebook. If there are any visible errors, feel free to leave a comment so that I can fix them. Also, let me know if there is any content you would like to see from me

Sources:

Mocha Documentation: (https://mochajs.org/)

--

--

Jay's Notebook

These are pages from my personal notebook, shared with the world.