Javascript Testing with Mocha (Everything You Need To Know)
An introduction to the well known javascript testing framework
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 ofdescribe()
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 ofit()
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/)