
What is the best way to structure my database?
In today’s digital age, data is the backbone of any successful organization.
Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation. It is a very important aspect of software development. The main objective of unit testing is to isolate written code to test and determine if it works as intended.
Unit testing is a crucial stage in the development process because, when done properly, it can aid in finding early code issues that could be more challenging to identify in subsequent testing phases.
In this article, I hope to show you how to write unit test for your Express API.
As a developer, you should always strive to write clean, maintainable, and reliable code. Unit testing is one of the ways to achieve this.
Early in the development cycle, writing unit tests enables the discovery of flaws before they contaminate later stages.
Before we start writing unit tests, we need to have a basic understanding of the following:
We will be using a simple Express API to demonstrate how to write unit tests. The API will be a simple blog API that allows users to create, read, update, and delete blog posts.
To get started, create a new folder and initialize a new Node.js project by running the following command in your terminal:
`npm init -y`
Next, install the following dependencies:
`npm i express mongoose nodemon mocha chai chai-http --save-dev`
Create a new file named app.js and add the following code:
const express = require('express');
const mongoose = require('mongoose');
const app = express();
mongoose.connect('mongodb://localhost:27023/blog', { useNewUrlParser: true, useUnifiedTopology: true });
app.use(express.json());
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
In the code above, we are importing the required dependencies, initializing the Express app, connecting to the MongoDB database, and setting up the server.
Next, create a new folder named routes and add a new file named blog.js. Add the following code to the file:
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.send('Hello World!');
});
module.exports = router;
In the code above, we are importing the required dependencies, initializing the Express router, and creating a simple GET route.
Next, add the following code to the app.js file:
const blogRoutes = require('./routes/blog');
app.use('/blog', blogRoutes);
In the code above, we are importing the blog routes and adding them to the Express app.
Create a new folder named models and add a new file named blog.js. Add the following code to the file:
const mongoose = require('mongoose');
const blogSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
body: {
type: String,
required: true
}
}, { timestamps: true });
module.exports = mongoose.model('Blog', blogSchema);
In the code above, we are importing the required dependencies, creating a new schema, and exporting the model.
Next, create a new folder named test and add a new file named blog.js. Add the following code to the file:
const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('../app');
const Blog = require('../models/blog');
const should = chai.should();
chai.use(chaiHttp);
In the code above, we are importing the required dependencies, initializing the Express app, and importing the Blog model.
Subscribe to our newsletter.
Now that we have set up the project, let's write the unit tests.
Before writing the unit tests, let's pay attention to the following keywords used in testing Express APIs:
Now that we have set up the project, let's write the unit tests.
Add the following code to the blog.js file:
describe('GET /blog', () => {
it('should get all the blog posts', (done) => {
chai.request(app)
.get('/blog')
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('array');
res.body.length.should.be.eql(0);
done();
});
});
});
In the code above, we are describing the GET route, and testing if the route returns a status code of 200, an array, and an empty array.
Add the following code to the blog.js file:
describe('POST /blog', () => {
it('should not create a blog post without title field', (done) => {
let blog = {
body: 'This is the body'
}
chai.request(app)
.post('/blog')
.send(blog)
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('errors');
res.body.errors.should.have.property('title');
res.body.errors.title.should.have.property('kind').eql('required');
done();
});
});
it('should create a blog post', (done) => {
let blog = {
title: 'This is the title',
body: 'This is the body'
}
chai.request(app)
.post('/blog')
.send(blog)
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('message').eql('Blog successfully added!');
res.body.blog.should.have.property('title');
res.body.blog.should.have.property('body');
done();
});
});
});
In the code above, we are describing the POST route, and testing if the route returns a status code of 200, an object, and an error message if the title field is not provided. We are also testing if the route returns a status code of 200, an object, and a success message if the title and body fields are provided.
Add the following code to the blog.js file:
describe('GET /blog/:id', () => {
it('should get a blog post by the given id', (done) => {
let blog = new Blog({
title: 'This is the title',
body: 'This is the body'
});
blog.save((err, blog) => {
chai.request(app)
.get('/blog/' + blog.id)
.send(blog)
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('title');
res.body.should.have.property('body');
res.body.should.have.property('_id').eql(blog.id);
done();
});
});
});
});
In the code above, we are describing the GET (by id) route, and testing if the route returns a status code of 200, an object, and the blog post with the given id.
Add the following code to the blog.js file:
describe('PUT /blog/:id', () => {
it('should update the blog post given the id', (done) => {
let blog = new Blog({
title: 'This is the title',
body: 'This is the body'
});
blog.save((err, blog) => {
chai.request(app)
.put('/blog/' + blog.id)
.send({
title: 'This is the updated title',
body: 'This is the updated body'
})
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('message').eql('Blog updated!');
res.body.blog.should.have.property('title').eql('This is the updated title');
res.body.blog.should.have.property('body').eql('This is the updated body');
done();
});
});
});
});
In the code above, we are describing the PUT route, and testing if the route returns a status code of 200, an object, and a success message if the blog post with the given id is updated.
To run the tests writen, we need to update the package.json file. Add the following code to the scripts object:
"test": "mocha"
Then run the following command in the terminal:
npm test
The tests should run successfully and the output should be similar to the one below:
Blog
GET /blog
✓ should get all the blog posts
POST /blog
✓ should not create a blog post without title field
✓ should create a blog post
GET /blog/:id
✓ should get a blog post by the given id
PUT /blog/:id
✓ should update the blog post given the id
5 passing (1s)
In this tutorial, we have learned how to write tests for a RESTful API using Mocha and Chai. We have also learned how to test the GET, POST, GET (by id), and PUT routes.
Stay up to date with everything that’s happening in the world of Artifical Intelligence.
In today’s digital age, data is the backbone of any successful organization.
Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation.
An open source distributed version control system, which makes tracking and merging code changes much easier.