Table of contents
Testing is a critical aspect of any software development project. This is because its omission will have a detrimental impact on user experience. To release a bug-free product, JavaScript testing is the ideal solution. Today we will talk about Node.js Unit Testing with Jasmine Framework.
JavaScript testing not only helps finding bugs in the early stage of development, but also assists in releasing stable software to its users. Features of Node.js also contribute to this aspect with the in-built capability of unit testing. Let’s analyze how this whole process works.
The framework deployed in Node.js unit testing was formerly called JsUnit in the early 2000s. Over time, this framework had a number of upgrades and now it has become Jasmine.
The Jasmine framework enables automated Node.js unit testing – an essential practice to develop modern web and mobile-based apps. That’s why companies need to hire Node.js developer so that they will utilize this practice.
Jasmin testing framework is a Behavior Driven Development (BDD) testing framework. So, there is no requirement of a JavaScript framework.
Therefore, Jasmine is highly suitable for the Node.js unit testing framework, websites, or other places where JavaScript based frameworks function effectively.
This is such a crucial aspect when you’re dealing with Node JS Unit Testing. It will help you to deal with the testing scenario in a better manner.
The different test case of the Jasmine Testing Framework:
As a call to global function ‘describe’, it considers the argument as function and String. The String provides a suite title while the global function is a code block for the implementation purpose.
It is a call to the global Jasmine testing function that also takes the form of a String and a function. String is the spec title, with the function a test.
A spec comprises expectations examining the state of code that you need test. Furthermore, there can be several ‘it’ functions in a describe block.
In a Jasmine testing framework, the expectation is an assertion that can either be true or false. There can be many assertions in one spec.
One can generate Expectations with an ‘expect’ function, taking the argument as the actual value. The argument is then clubbed with a Matcher function, i.e. the expected value.
Each Matcher test case implements a Boolean comparison between the expected and actual value with Matchers deployed to compare both.
If all Matchers are true, the test is passed. If not, it is deemed as a failure. Some Matcher functions consist of ‘toBeTruthy’ and ‘toBe’.
To setup the Jasmine testing framework, user performs the following steps:
The user must then perform additional steps to complete setting up Jasmine Testing framework.
The user must perform following steps:
The Jasmine test framework creates a configuration json and spec directory for users with the latter storing all test files, enabling the Jasmine framework to execute them.
The json file stores particular config data about the Jasmine testing framework.
The user must perform the following steps:
The configuration file is usually under the name jasmine.json in the spec/support folder. The file enumerates both the spec and source files that the user needs Jasmine node framework to include. A coding snippet explains this.
{ “spec_dir”: “spec” // Shows Successful Execution “spec_files: [ “**/*[sS/] pec.js” // Shows Successful Execution ], “helpers”: [ “helpers/**/*.js” ], “stopSpecOnExpectationFailure”: false, “random”: false
Note – Spec directory has been specified in this example. When the Jasmine testing framework is executed, it searches for every directory test. Another important aspect is spec_files parameter. Any created test files must be appended with keyword ‘spec’.
To use Jasmine test framework properly and to conduct Node JS Unit Testing, refer to the next example. Initially, a module is defined, following which, two numbers are added.
A separate code file comprising test code is then added with the Jasmine test framework deployed to test the ‘Add’ function as needed.
User performs following steps:
var exports=module.exports={}; exports.AddNumber=function(a,b) { return a+b; };
Note – The keyword ‘exports’ guarantees that defined functionality is accessible by other files. A function ‘AddNumber’ takes two parameters, a and b, and adds them to the ‘exports’ module ensuring public accessibility. Lastly, function returns the added value of the two parameters.
var app=require("../Add.js"); describe("Addition",function(){ it("The function should add 2 numbers",function() { var value=app.AddNumber(5,6); expect(value).toBe(11); }); });
Note – Add.js file is included to test ‘AddNumber’ function in file. In the Node.js testing framework module that is created, the first part describes a name (‘’Addition”).
A description with ‘it’ method is next. Addnumber is then invoked along with sending parameters 5 & 6, passed onto the AddNumber method. Lastly, a comparison of the actual test is done.
Following screen appears.
C:UsersAdministratorProjectsSample>jasmine
Started
.
.
.
1 spec, 0 failure
Note– Any Errors are displayed on the screen.
To test Node.js unit test framework, Jasmine must be installed along with Node package manager. Test code is written separately, with ‘spec’ appended to the file name.
Without this, the Jasmine test framework is unable to detect files. Lastly, the test is run by executing Jasmine testing framework command, finding all files with word ‘spec’ attached.
To setup and download dependencies, users use Node.js Unit Testing Framework from the official package manager (npm).
The major advantage of npm is that it initializes an empty project directory with the option of init command.
User performs following steps:
{ "name": "Hello World", "version": "0.0.1", "description": "Simple Hello World demo app.", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "author": "", "license": "ISC" }
A directory for Jasmine Unit Testing along with the server source code is set up. Usually, tests written in the Jasmine testing framework module are known as specs and saved in the directory.
mkdir app mkdir spec
At this stage, the project tree must have the below pattern:
├── app
├── node_modules
├── package.json
└── spec
To write specs in Jasmine test framework, user perform the following steps:
Following file appears
{ "name": "Hello World", "version": "0.0.1", "description": "Simple Hello World demo app.", "main": "index.js", "scripts": { "test": "./node_modules/.bin/jasmine-node spec" }, "author": "", "license": "ISC" }
The following steps are performed –
describe("Hello World Server", function() { });
Note – First argument provides a brief description of the tested feature, while second executes expectations.
The user must ensure that the server returns to HTTP status OK (status code 200) when a GET request is sent to the root path.
describe("Hello World Server", function() { describe("GET /", function() { }); });
describe("Hello World Server", function() { describe("GET /", function() { it("returns status code 200", function() { }); }); });
var request = require("request"); var base_url = "http://localhost:3000/" describe("Hello World Server", function() { describe("GET /", function() { it("returns status code 200", function() { request.get(base_url, function(error, response, body) { }); }); }); });
var request = require("request"); var base_url = "http://localhost:3000/" describe("Hello World Server", function() { describe("GET /", function() { it("returns status code 200", function() { request.get(base_url, function(error, response, body) { expect(response.statusCode).toBe(200); }); }); }); });
Note – The procedure is nearly complete, but there is a chance that the it block may finish before the expectation, as the Node.js testing framework is an asynchronous environment.
To avoid this, the done callback function – a callback only in Jasmine-node is used to synchronize expect with it:
var request = require("request"); var base_url = "http://localhost:3000/" describe("Hello World Server", function() { describe("GET /", function() { it("returns status code 200", function(done) { request.get(base_url, function(error, response, body) { expect(response.statusCode).toBe(200); done(); }); }); }); });
Note – You should call the demo function should only if the expectation is executed. If there is no call to done() or reason (code error or similar), Jasmine terminates this ‘it’ block and considers it as a failed example.
The user performs following steps:
app.get("/", function(req, res) { res.send("Hello World"); });
Note – At this point, the user should ensure that the app looks like this :
var express = require('express'); var app = express(); app.get("/", function(req, res) { res.send("Hello World"); }); app.listen(3000);
Note – This is to check if the spec description and implementation align with each other.
The following output appears.
> [email protected] test /home/igor/hello_world > jasmine-node spec .. Finished in 0.007 seconds 2 tests, 0 assertions, 0 failures, 0 skipped
Read also: Exploring The Best Node.js Application Examples For Big Enterprise
Through a Hello World Generator, a user can request the required number of Hello Worlds with the server returning them as JSON arrays.
To do so, the user can create a function that considers a number as the parameter to return an array with those many ‘Hello World’ strings in them.
The user performs the following steps:
touch spec/generatorSpec.js var generator = require("../app/generator"); describe("Hello World Generator", function() { it("returns an array", function() { expect(generator.generateHelloWorlds(0)).toBe([]); }); it("returns the correct number of Hello Worlds", function() { var result = generator.generateHelloWorlds(3); expect(result.length).toBe(3); }); it("returns only Hello Worlds", function() { var result = generator.generateHelloWorlds(3); result.forEach(function(element) { expect(element).toBe("Hello World"); }); }); });
touch app/generator.js exports.generateHelloWorld = function(number) { var result = []; for(var i=0; i < number; i++) { result.push("Hello World"); } return result; }
Note – In this case, there is an implementation of function as part of the export’s namespace. This tells the node to make the function visible to other modules.
var request = require("request"); describe("Hello World Server", function() { describe("GET /", function() { it("returns status code 200", function(done) { request.get("http://localhost:3000", function(error, response, body) { expect(response.statusCode).toBe(200); done(); }); }); it("returns Hello World array", function(done) { request.get("http://localhost:3000?number=3", function(error, response, body) { expect(body).toBe(JSON.stringify(["Hello World", "Hello World", "Hello World"])); done(); }); }); }); });
var generator = require('./generator'); var express = require('express'); var app = express(); app.get("/", function(req, res) { var number = req.params.number; var helloWorldArray = generator.generateHelloWorlds(number); res.send(200, helloWorldArray); }); app.listen(3000);
The JavaScript framework has certainly progressed by leaps and bounds since its inception more than two decades ago.
Writing web and mobile apps is now extremely simple and straightforward, and with the Jasmine Node JS, it would not be an exaggeration to even call testing a pleasurable experience.
We hope you had a great time reading this article and it proves to be of great value for any Node.js Web App Development Company who is dealing with Jasmine Framework.