Testing is a very important part of any backend application. It helps you catch bugs early and makes sure your application and APIs work as expected even after changes. In Node.js, Mocha and Supertest are two popular tools used together for API testing.

Mocha is a feature-rich JavaScript test framework running on Node.js and the browser, while Supertest is a library for testing HTTP requests and responses.

This article explains how to use Mocha and Supertest to test your application and APIs and how to use them with a real example.


What is Mocha?

Mocha is a testing framework for Node.js. It gives structure to your tests and helps you write them in an organized way. Mocha provides a rich set of features for testing JavaScript applications, including support for asynchronous testing, hooks, and various reporting options.

What does Mocha do?

  1. describe() to group test cases
  2. it() to define individual test cases
  3. Clear pass/fail output in the terminal

Mocha does not test APIs by itself. It only runs and manages tests.

Install Mocha

To install Mocha globally, run the following command:

npm install -g mocha

To install Mocha as a development dependency in your project, run:

npm install --save-dev mocha

For macOS and Linux

sudo npm install --save-dev mocha

Run Mocha

To run Mocha, create a folder named `test` in your project directory and add your test files there, let's say named test.js:

mocha test/test.js

Add mocha in package.json

You can also add a test script in your package.json file to run Mocha:


"scripts": {
  "test": "mocha"
}

Now you can run your tests using npm:

npm test

Supertest

Supertest is a library that provides a high-level abstraction for testing HTTP APIs. It allows you to make requests to your API and assert the responses in a clean and readable way.

Install Supertest

npm install --save-dev supertest

Install Supertest on macOS and Linux

sudo npm install --save-dev supertest

Why use Supertest with Mocha?

Supertest is designed to work seamlessly with Mocha, providing a clean and expressive way to test HTTP APIs. It allows you to make requests to your API endpoints and assert the responses in a readable and maintainable way.

  1. Easy to learn and use
  2. Fast API testing
  3. Works well with Express
  4. Helps avoid breaking APIs in production
  5. Good for real-world backend projects

Best Practices

  1. Keep tests inside a test folder
  2. Test both success and failure cases
  3. Do not start the server in test files
  4. Write small and clear test cases
  5. Run tests before pushing code
  6. Use descriptive test names
  7. Organize tests by feature or module

Example of Mocha and Supertest

Let's create a simple Express application and write tests for its API using Mocha and Supertest.

Create a Simple Express Application

  /* app.js */
import express from "express";
const app = express();

app.use(express.json());

app.get("/", (req, res) => {
  res.status(200).send("Hello World");
});

app.get("/api", (req, res) => {
  res.status(200).json({ message: "API is working" });
});

export default app;
  /* server.js */
import app from "./app.js";

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Write Tests with Mocha and Supertest

Now let's write tests for our API endpoints using Mocha and Supertest. Note that Mocha doesn't include assertion libraries by default, so we'll use Node.js built-in assert module for simplicity, or you can install Chai for more expressive assertions.

  /* test/test.js */
import request from "supertest";
import app from "../app.js";
import assert from "assert";

describe("API Tests", () => {
  it("should return Hello World on root endpoint", async () => {
    const response = await request(app).get("/");
    assert.strictEqual(response.status, 200);
    assert.strictEqual(response.text, "Hello World");
  });

  it("should return API working message", async () => {
    const response = await request(app).get("/api");
    assert.strictEqual(response.status, 200);
    assert.deepStrictEqual(response.body, { message: "API is working" });
  });
});

Run Tests

To run the tests, use the following command:

npm test

The tests will run and display the results in the terminal. You should see output indicating which tests passed or failed.

Additional Tips

  • Use beforeEach and afterEach hooks in Mocha to set up and tear down test data.
  • For more advanced assertions, install Chai: npm install --save-dev chai and use expect syntax.
  • Consider using test coverage tools like Istanbul (nyc) to measure how much of your code is tested.
  • Run tests in CI/CD pipelines to ensure code quality before deployment.

Conclusion

Mocha and Supertest are powerful tools for testing Node.js applications. Mocha provides a flexible testing framework, while Supertest simplifies HTTP API testing by offering an easy-to-use interface for making requests and asserting responses.

By combining these two tools, you can create comprehensive test suites that ensure your APIs work as expected and help catch bugs early in the development process. Remember to write tests for both success and error scenarios, and integrate testing into your development workflow for better code quality.