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
, andshould
.
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 theaxios.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 usingstub.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.
Hey Tech Enthusiasts!
I’m Avinash, a passionate tech blogger with over 13+ years of experience in the trenches of software engineering.
You could say I’ve worn many hats in my journey – from full-stack developer crafting beautiful and functional applications to Solution Architect, designing the architecture for complex systems.
Over the years, I’ve delved into a vast arsenal of languages and tools, including the Generative AI (LLMs, LLM-Proxy, Observability, Prompt Engineering), .NET family (.NET, .NET Core), PHP, Rust, Python, the JavaScript frameworks (Angular, React, Node.js), and databases like MySQL, SQL Server, MongoDB.
As the cloud revolutionized our world, I’ve become well-versed in both Azure and GCP platforms, wielding Docker for containerization and CI/CD pipelines to streamline development workflows.
Here on my blog, I aim to share the knowledge I’ve accumulated and the lessons I’ve learned along the way. Whether you’re a seasoned developer or just starting your coding adventure, I want to provide you with insightful, practical articles that tackle real-world tech challenges.
Get ready to explore the latest advancements, delve into programming concepts, and discover efficient solutions to your development dilemmas. So, buckle up, tech enthusiasts – let’s embark on this exciting journey together!