One of the important task which most of the developers ignores ( i used to ignore too ) is writing unit tests for your code. Unit test is not just a help to tester or quality assurance team but its the proof of quality of your code.
In this tutorial i am going to cover how to test your REST api’s written in ExpresJS using famous unit testing tool called Mocha and supertest.
Table of Contents
What is Mocha ?
Mocha is simple and easy to use test framework. It runs on Node.js and allows you to develop test cases for your program and execute them in serial with proper reporting.
To use mocha i suggest you to install it and as global package using following command.
What is supertest ?
Supertest is library written to test HTTP calls in node.js. So if you want to write test cases which going to do some HTTP calls ( GET, POST, PUT etc ) then this might be the useful tool for you.
Our project :
Let’s develop an expressJS app with some routes and test whether those are giving expected result or not.
Here is package.json :
"name": "MochaTest",
"version": "0.0.1",
"dependencies": {
"body-parser": "^1.13.2",
"express": "^4.13.1"
}
}
Install dependencies by running
on terminal.
Here is Server file.
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
var router = express.Router();
router.get('/',function(req,res){
res.json({"error" : false, "message" : "Hello !"});
});
router.post('/add',function(req,res){
res.json({"error" : false, "message" : "success", "data" : req.body.num1 + req.body.num2});
});
app.use('/',router);
app.listen(3000,function(){
console.log("I am listening at PORT 3000");
})
Writing test cases :
Let’s move ahead and write some unit test for above program. First you need to install mocha, should and supertest in your project. It’s better if we add them in dev dependencies.
1 : Install mocha.
2 : Install should.
3 : Install supertest.
After running above commands your package.json should look this.
"name": "MochaTest",
"version": "0.0.1",
"dependencies": {
"body-parser": "^1.13.2",
"express": "^4.13.1"
},
"devDependencies": {
"mocha": "^2.2.5",
"should": "^7.0.2",
"supertest": "^1.0.1"
}
}
Let’s create one folder called “test” and place “test.js” inside it. Just to separate it from rest of the code.
Before writing unit test, let’s discuss how the building block will look.
You need to provide description of unit test using “describe” function and use “it” to define several unit test cases into it. “it” provides us “done” function is used to indicate the end of test case.
Let’s write following unit test case.
- Access home page – should return response code 200
- Add router should add two numbers.
- 404 for other router
Test case 1 : Access home page
var should = require("should");
// This agent refers to PORT where program is runninng.
var server = supertest.agent("http://localhost:3000");
// UNIT test begin
describe("SAMPLE unit test",function(){
// #1 should return home page
it("should return home page",function(done){
// calling home page api
server
.get("/")
.expect("Content-type",/json/)
.expect(200) // THis is HTTP response
.end(function(err,res){
// HTTP status should be 200
res.status.should.equal(200);
// Error key should be false.
res.body.error.should.equal(false);
done();
});
});
});
Assuming you have installed mocha globally, run your node program and listen on port 3000. Open another tab and run
to start test.
Here is screenshot.
Test case 2 : Add router should add two numbers.
var should = require("should");
// This agent refers to PORT where program is runninng.
var server = supertest.agent("http://localhost:3000");
// UNIT test begin
describe("SAMPLE unit test",function(){
// #1 should return home page
it("should return home page",function(done){
-------------------------------------
});
it("should add two number",function(done){
//calling ADD api
server
.post('/add')
.send({num1 : 10, num2 : 20})
.expect("Content-type",/json/)
.expect(200)
.end(function(err,res){
res.status.should.equal(200);
res.body.error.should.equal(false);
res.body.data.should.equal(30);
done();
});
});
});
Here is test case response.
Test case 3 : 404 Error.
var should = require("should");
// This agent refers to PORT where program is runninng.
var server = supertest.agent("http://localhost:3000");
// UNIT test begin
describe("SAMPLE unit test",function(){
// #1 should return home page
it("should return home page",function(done){
---------------------------------
});
it("should add two number",function(done){
---------------------------------
});
it("should return 404",function(done){
server
.get("/random")
.expect(404)
.end(function(err,res){
res.status.should.equal(404);
done();
});
})
});
Here is the output.
Let’s see some failure case
Just change the equal value in second test to other than 30 and see the response. Like this.
var should = require("should");
// This agent refers to PORT where program is running.
var server = supertest.agent("http://localhost:3000");
// UNIT test begin
describe("SAMPLE unit test",function(){
// #1 should return home page
it("should return home page",function(done){
--------------------------------
});
it("should add two number",function(done){
//calling ADD api
server
.post('/add')
.send({num1 : 10, num2 : 20})
.expect("Content-type",/json/)
.expect(200)
.end(function(err,res){
res.status.should.equal(200);
res.body.error.should.equal(false);
res.body.data.should.equal(40);
done();
});
});
it("should return 404",function(done){
---------------------------
})
});
You should get one failure test case.
Conclusion:
Writing unit test is like never-ending process. You can write almost all kind of combination of test cases. You should learn and start writing test cases right after you finish one particular module,don’t wait for the project to finish.
you are always super shahid….
Nice tutorial….
Nice tutorial………thk u shahid
Your welcome.
How to protect database credentials in server.js?
Answered already here.
In last case we are getting Uncaught Exception: excepted 30 to be 40. How to handle these this Exception in mocha, Please tell me
Which case you are talking about ?
Thanks you for nice tutorial.
But I have a problem: My API will response ‘[]’ if after query database, result haven’t data or have a error. And I want to catch error from mocha when I request with wrong type of data.
Thanks and please help me!
Hey,
I am facing the same issue, Did you happen to find a reason or a solution to this?
what is the naming convention for unit test file name??
Like in a big module: module_spec_methodName.js
for ex: string_spec_match.js
Is it right??
Getting below error after .double callback warning.
Uncaught TypeError: Cannot read property ‘status’ of undefined.
Ok, I am wondering why you stated the expect(200) in Step 1. But then in that same script, in the .end statement is where you are testing the actual response status coming back from the server. Is there a reason for doing both??
Thanks you for nice tutorial
@Anthony Jackson
Actually, he doesn’t only do it in step 1, but in the others as well. For example in step 3 with 404.
From what I could see the expect doesn’t actually do anything used in this way. Try to change the value in the expect and the result of the test will not change. I’m not sure either why the expect is used in this examples?
server.expect() i believe look for HTTP code.
in case one mentioned by @Anthony, we are checking for “good” use and we are getting the response. Response should have header code 200 which is OK in http verb.
Same goes for case you mentioned, 404 is not found object.
How to loop it() reading test cases from json file.
Great, tell me one more thing, how to handle flash messages ?
On each `error` or `success` of API I’m redirecting on same page with flash messages.
I can write like this `res.header[‘location’].should.include(‘/home’)`.
But I need to verify either it is redirecting with error or success.
Thanks..!!
thx for d tutorial!!!! u rock!
This is totally misleading – these are not unit test’s – these are integration tests which run against your node server
I never said it is. I said we can use Mocha to write unit tests.
I am new to node .. I am getting the following error ..SAMPLE unit test
1) should return home page
0 passing (38ms)
1 failing
1) SAMPLE unit test should return home page:
Uncaught TypeError: Cannot read property ‘should’ of undefined
at Test. (Tests/test.js:24:21)
at Test.assert (node_modules/supertest/lib/test.js:179:6)
Any idea what is happening..
thanks
Hey Raj, you are using ‘should’ against null or undefined value. Make sure that the response object key/property has a value. For instance, ‘res.body.error’ might giving you a null value or undefined.
Hope this helps.
please i need the link between restful nodejs api using orm sequelize and mysql database
Nice article.
One question: How do we display a customised error message when one of the response parameter/field is missing (as we get Assertion error in this case and need a customised error to show)
Hello,
Is it necessary for us to use server.js in here. If we want to test a REST api, server.js is not necessary ? It is not clear for me. Can we do API automation with just SuperTest and Mocha?
Under end function you have to use
if (err) return done(err);
otherwise your expectation before end clause will be ignored.
Thank you for this great tutorial.
This tutorial is more of the acceptance or functional tests rather than unit tests.
I thought unit tests was meant to test the internal functions