2 Powerful Testing Suits: sinon and chai using nodejs

sinon and chai using nodejs: Sinon and Chai are both popular JavaScript libraries used for testing, but they serve different purposes.

Sinon:

  • Sinon.js is primarily used for creating spies, stubs, and mocks in your test cases.
  • It’s particularly useful when you want to replace a function with a spy (to track its calls), a stub (to control its behavior), or a mock (to set expectations on its behavior).
  • Sinon can be used alongside testing frameworks like Mocha, Jasmine, or Jest.

Chai:

  • Chai is an assertion library that provides a fluent interface for making assertions in your tests.
  • It’s useful for writing expressive and readable assertions to validate the behavior of your code.
  • Chai offers different assertion styles including expect, assert, and should.

Step by Step guide

Here’s a step-by-step guide on how to use Sinon and Chai together in your tests:

Installation:

Install Sinon and Chai using npm or yarn:

npm install sinon chai --save-dev

or

yarn add sinon chai --dev

Setup: sinon and chai using nodejs

  • If you’re using a test runner like Mocha, Jasmine, or Jest, make sure to configure it to work with Sinon and Chai.
  • For Mocha, you can include Chai’s expect interface and Sinon’s assertions in your test setup file:
// test/setup.js
const chai = require('chai');
const sinonChai = require('sinon-chai');

chai.use(sinonChai);
global.expect = chai.expect;
global.sinon = require('sinon');

Writing Tests:

Import Sinon and Chai into your test files:

const sinon = require('sinon');
const { expect } = require('chai');

Use Sinon to create spies, stubs, or mocks as needed:

const myFunc = sinon.stub();
myFunc.returns(42);

myFunc();
expect(myFunc).to.have.been.calledOnce();
expect(myFunc).to.have.returned(42);

Use Chai’s assertion methods to make assertions about your code’s behavior:

const result = myFunc();
expect(result).to.equal(42);

Read Also : WhatsApp-like Chat App: Storing and Downloading Images and Videos in MongoDB using node js

Example:

Let’s say you have a function that fetches user data from an API:

// user.js
const axios = require('axios');

async function getUserData(userId) {
    try {
        const response = await axios.get(`/api/users/${userId}`);
        return response.data;
    } catch (error) {
        throw new Error('Failed to fetch user data');
    }
}

module.exports = {
    getUserData
};

You can write a test for this function using Sinon and Chai to spy on the axios module and assert the behaviour of getUserData:

// user.test.js 
const {getUserData} = require('./user');
const axios = require('axios');

describe('getUserData', () => {
    it('fetches user data from API', async () => {
        const axiosStub = sinon.stub(axios, 'get').resolves({
            data: {
                name: 'John',
                age: 30
            }
        });
        const userData = await getUserData(123);
        expect(userData).to.deep.equal({
            name: 'John',
            age: 30
        });
        expect(axiosStub).to.have.been.calledOnceWithExactly('/api/users/123');
        axiosStub.restore();
    });
    it('throws an error when API request fails', async () =>
    {
        sinon.stub(axios, 'get').rejects(new Error('API request failed'));
        try {
            await getUserData(123);
        } catch (error) {
            expect(error.message).to.equal('Failed to fetch user data');
        }
        axios.get.restore();
    });
});

In this example:

  • We use sinon.stub().resolves() to create a stub for the axios.get method.
  • We then configure the stub to resolve with mock data when called with a specific URL (/api/users/123) in the first test case and to reject with an error in the second test case.
  • After the test, we restore the original behaviour of the axios.get method using stub.restore() to ensure that it doesn’t affect other tests.

This way, Sinon allows us to control the behavior of external dependencies (like HTTP requests) in our tests, making them more reliable and deterministic.