CodeWithMMAK
API AutomationIntermediate

API Automation with SuperTest, Mocha, and Chai: A Complete Guide

Master API automation using SuperTest for HTTP assertions, Mocha as the test runner, and Chai for BDD-style assertions. Learn how to generate realistic test data with FakerJS.

CodeWithMMAK
December 11, 2022
13 min

Introduction

🎯 Quick Answer

API Automation with SuperTest is a powerful approach for testing HTTP servers in Node.js. It provides a high-level abstraction for making requests and asserting on responses (status codes, headers, body) in a single, fluent API. When combined with Mocha (test runner), Chai (assertion library), and FakerJS (data generation), it creates a robust, scalable, and highly readable framework for validating RESTful services and microservices.

Automating API tests can be done using several tools. In this article, we will be using SuperTest, Mocha, and Chai. We will use FakerJS to generate realistic test data.

📖 Key Definitions

SuperTest

A Node.js library for testing HTTP servers. It allows you to send requests and assert on the response in a single chain.

Mocha

A flexible JavaScript test framework that runs on Node.js, providing the structure for your test suites and cases.

Chai

An assertion library that provides BDD (Expect/Should) and TDD (Assert) styles for validating test results.

FakerJS

A library used to generate dynamic, realistic data like names, emails, and addresses, ensuring tests aren't reliant on static, repetitive data.

Why SuperTest?

SuperTest is particularly powerful because it can test an Express app without actually starting the server on a network port, making tests faster and more isolated. Key features include:

  • Fluent API: Chain requests and assertions together (e.g., .get('/user').expect(200)).
  • Built-in Assertions: Easily check status codes, content types, and headers without extra libraries.
  • Integration: Works seamlessly with any Node.js test runner like Mocha or Jest.

🚀 Step-by-Step Implementation

1

Initialize the Project

Create a new folder and run npm init -y to set up your Node.js environment.

2

Install Dependencies

Install the necessary packages:

Code Snippet
npm install --save-dev supertest mocha chai mochawesome @faker-js/faker
3

Create a Test Suite

Create a test directory and a file like api.test.js.

4

Write a GET Request Test

Use request(url).get(path) and chain .expect() to validate the response status and headers.

5

Implement Dynamic Data with Faker

Use faker to generate unique payloads for POST or PUT requests to avoid data collisions.

6

Execute and Report

Run npx mocha to execute tests. Use mochawesome for beautiful HTML reports.

Example: Advanced POST & GET Flow

Code Snippet
const request = require('supertest');
const expect = require('chai').expect;
const { faker } = require('@faker-js/faker');

describe('User Management API', () => {
    const baseUrl = 'https://reqres.in';
    let userId;

    it('should create a new user with dynamic data', async () => {
        const payload = {
            name: faker.person.fullName(),
            job: faker.person.jobTitle()
        };

        const res = await request(baseUrl)
            .post('/api/users')
            .send(payload)
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(201);

        expect(res.body.name).to.equal(payload.name);
        userId = res.body.id;
    });

    it('should fetch the created user details', async () => {
        const res = await request(baseUrl)
            .get(`/api/users/2`) // Using static ID for demo
            .expect(200);
        
        expect(res.body.data).to.have.property('id');
        expect(res.body.data.first_name).to.be.a('string');
    });
});

Common Errors & Best Practices

⚠️ Common Errors & Pitfalls

  • Mixing Callbacks and Promises

    Using the .end() callback while also using async/await. Stick to one style (preferably async/await) to avoid unhandled rejections.

  • Ignoring Response Body Validation

    Only checking for 200 OK without verifying that the returned JSON actually contains the expected data.

  • Hardcoded Auth Tokens

    Storing sensitive tokens in the code. Use environment variables or a before() hook to fetch tokens dynamically.

Best Practices

  • Use async/await for cleaner, more readable asynchronous test code.
  • Implement global hooks (before, after) to handle setup and teardown tasks like database cleaning.
  • Use .expect(regex) for flexible header and body assertions.
  • Group related tests into describe blocks for better organization and reporting.

Frequently Asked Questions

Can SuperTest test local Express apps?

Yes! You can pass the app object directly to request(app) without calling app.listen().

How do I handle file uploads?

Use the .attach('fieldname', 'path/to/file') method provided by SuperTest.

How do I debug failed requests?

You can log the response body in the .catch() block or use a debugger to inspect the res object.

Conclusion

SuperTest, combined with Mocha and Chai, offers a professional-grade solution for API automation. Its ability to handle complex HTTP assertions with a simple syntax makes it a top choice for Node.js developers and QA engineers alike.

📝 Summary & Key Takeaways

API automation with SuperTest, Mocha, and Chai provides a high-level, fluent interface for testing HTTP services. SuperTest excels at making requests and asserting on responses, while Mocha provides the test structure and Chai offers flexible assertion styles. By incorporating FakerJS for dynamic data and following async/await patterns, teams can build reliable, maintainable, and fast API test suites that integrate perfectly into modern CI/CD workflows.

Share it with your network and help others learn too!

Follow me on social media for more developer tips, tricks, and tutorials. Let's connect and build something great together!