Callbacks & Promise in node js

Today i will share the Node JS callback and promise system. Node JS asynchronous event based language which mean system not wait for task for completion and forward to next instruction. So as an example if we try to read a file from file system and then print read contents that may not work.

const fs = require ("fs");
let content = fs.reafile ("file.txt"):
console.log (content):

In above code, interpretor jump to console log even before read file call completion due to asynchronous behavior.
This issue is resolved by Node JS by making all its core APIs async friendly through callbacks. Above example actually work like below.

const fs = require ("fs");
let content = fs.reafile ("file.txt", function (err, data){
     if (err ){
          console.log (err);
     }
     console.log (data):
}):

Here readfile api provide a callback function which executed after file read operation. It have two arguments err and data. Data have the success response, in case of readfile api, file contents.
Node JS core APIs work like that. Provide a callback function with error and response as parameters. We can implement our callbacks similar to this for asynchronous tasks.

funtion asyncfunction (inp, callback ){
     // do some asyns task
     const http = require ("http");
     http.get (url, function (err, response){
         callback (response);
     });
}

Above function can be used like

asyncfunction( data, function (httpResponse) {
      console.log( httpResponse);
});

In this case we can get interesting pattern like below.

 func1(data, function() {
    data.mod1 = 1;
    func2(data, function() {
        data.mod2 = 2;
        func3(data, function() {
            data.mod3 = 3;
            func4(data, function() {
                 data.mod4 = 4;
                 console.log( data);
            })
        });
    });
});

Above code show hierarchy of callbacks, Also famously called Callback Hell. This is problematic due to Poor readability & Poor manageability. Their are multiple solutions for ignore callback hells.
First to use modular code like I previously done in asyncfunction.

Second approach is to use Promises. Promise give us better control of asynchronous code.
Promise have two results states. Resolve & Reject. In Core Node JS we can use promise like that

function MyPromisedFunc() {
    return new Promise( resolve, reject ) {
         http.get(url, function(err, response) {
             if( err ) {
                  reject(‘Error in http response’)
             }
             resolve(response);
        });
   });
 }

return MyPromisedFunc() .then(function(response) {
     console.log(response);
 }).catch(function(err) {
     console.log(err); 
 });

Above code is more readable and manageable then callback code. Any time of our async code when we get actual response, we only need to resolve promise, If we get error the we reject the promise.
This further handle by then & catch blocks.
This is more look clear in multiple async function which need to run synchronously.

return MyPromisedFunc1()
     .then(MyPromisedFunc2)
     .then(MyPromisedFunc3)
     .then(MyPromisedFunc4) 
     .then(function(response) {
          console.log(response);
     }).catch(function(err) {
          console.log(err); 
     });

Now we executed four asynchronous functionalities in sync manner with better manageability.
Promise core api functionality is still very much limited in terms of functionality compare to third party Promise libraries like bluebird, Q Promise and more.

Example in bluebird support execution in parallel with better control.

const bluebirdPromise = require(‘bluebird’);
return bluebirdPromise.all([
     MyPromisedFunc1(),
     MyPromisedFunc2(),
     MyPromisedFunc3(),
     MyPromisedFunc4() ],
     .then(function(responseArray) {
           console.log(responseArray[0]);
           console.log(responseArray[1]);
           console.log(responseArray[2]);
           console.log(responseArray[3]); 
     }).catch(function(err) {
          console.log(err); 
     });

Node REST API Testing with Jasmine

In last article REST using Node/Express & Mongoose , I talk about setting REST APIs in NodeJS, Express & Mongoose. Today I will discuss unit testing for REST APIs using Jasmine.

Jasmine is behavioral testing framework for javascript applications. It provide easy to write & understand testing rules. While it can be downloaded from https://github.com/jasmine/jasmine. In node js we would use npm package named jasmine-node.

$ npm install --save jasmine-node

We also install request package for easy http calls.

$ npm install --save request

Now create a test folder let we name it spec. We can define our test cases in this folder. Let create a file names hello.spec.js and Put following code into it

describe("Hello World Suite", function() {
    it("check if text is 'Hello World'", function(done) {
        let text = "Hello World";
        expect(text).toBe("Hello World");
        done();
    });
   it("check if another text is 'Hello World'", function(done) {
        let text = "Not Hello World";
        expect(text).toBe("Hello World");
        done();
    });
});

Now we run command

$ node_modules/.bin/jasmine-node spec

This command generate assert failures for second test like below

Failures:

1) Hello World Suite check if another text is 'Hello World'
 Message:
 Expected 'Not Hello World' to be 'Hello World'.

2 tests, 2 assertions, 1 failure, 0 skipped

If we change text in second test from “Not Hello World” to “Hello World”  and re run command. We will get assert success like below .

2 tests, 2 assertions, 0 failures, 0 skipped

In above test “describe” work as Test Suite, So it can have many related tests, Let example for particular form field data validations, So all validation like not-empty, data type, duplicate can be part of single suite. describe have definition which show use of suite

individual tests inside described via “it”, which have suite description as first argument and callback as second.

We need to statement for compile a test. First a expect statement which is test assertion and other done function which notice the framework to completion of test. We can do many types of assertions

assert().toBe()
assert().toBeDefined() AND assert().toBeUndefined()
assert().toBeFalsy() AND assert().toBeTruthy()
assert().toBeNull()
assert().toEqual()
assert().toMatch()
assert().toThrow()

AND More....

Let we write test for previously REST APIs. Create a file called users.spec.js in spec folder.

var request = require("request");

var base_url = "http://localhost:3000/users"

let User = {
   _id:1,
   name:'',
   email:'',
   password:''
};

describe("Users List API Exists", function() {
     describe("GET /users", function() {
         it("returns status code 200", function(done) {
             request.get(base_url, function(error, response, body) {
             expect(response.statusCode).toBe(200);
             done();
         });
    });
 });

Above test check whether List API is available, It verify this by checking response status code is equal to 200 or not. Add another test to inner describe

it("API Response should be valid json", function(done) {
    request.get(base_url, function(error, response, body) {
        expect(() => {
            JSON.parse(body);
        }).not.toThrow();
        done();
    });
 });

Above test check if response is valid json or not. When invalid json as response return the native JSON parse function throw error which handled by expect ” not -> toThrow”. So assertion failed while in case of valid json assertion passed.

it("API Response should be valid array of user objects", function(done) {
     request.get(base_url, function(error, response, body) {
        let users = JSON.parse(body);
        const userRows = users.map((userRow) => {
            expect(JSON.stringify(Object.keys(User).sort()) ===     JSON.stringify(Object.keys(userRow).sort())).toBeTruthy();
        });
        done();
    });
 });

Above test goes further more and check return fields is valid. This test can be ignored in case of no restriction for fields returned in response.

I will discuss more on jasmine on API testing on further articles.

All code is hosted on Github