Applying React and Typescript API Calls unit test using Sinon


Purpose:


The objective of this document is to describe guidance, recommendations, and practices for applying developer test for API calls using Sinon library for mocking API calls.

Prerequisites:


This article mainly targets people with the knowledge of the followings:

-        React

-        TypeScript

-        NodeJS

-        Unit testing with Jest


Overview:
Sinon is a standalone and test framework agnostic JavaScript test spies, stubs and mocks.
Let’s go through some important methods we can use from Sinon during our unit test.

·     Sandboxes
var sandbox = sinon.createSandbox();
Creates a new sandbox object with spies, stubs, and mocks.
var sandbox = sinon.createSandbox(config);
The sinon.createSandbox(config) method is often an integration feature, and can be used for scenarios including a global object to coordinate all fakes through.
Sandboxes are partially configured by default such that calling:
var sandbox = sinon.createSandbox({});
·     Stubs
Test stubs are functions (spies) with pre-programmed behavior.
They support the full test spy API in addition to methods which can be used to alter the stub’s behavior.
As spies, stubs can be either anonymous, or wrap existing functions. When wrapping an existing function with a stub, the original function is not called

var stub = sinon.stub();
Creates an anonymous stub function
var stub = sinon.stub(object, "method");
Replaces object.method with a stub function. An exception is thrown if the property is not already a function.

     Using Sinon in testing Api Calls:
Let’s Check the following service and start performing unit test for it.



export class NetworkLibraryService {
 
  static fetchNetworkLibraries(): Promise<void> {
   // invoke Method is Creating Http Request to call GetNetworkLibraries Api         Method
    return NetworkLibraryService.invoke(
      'GetNetworkLibraries',
      null
    )
  }
}



Now we need to implement unit test for this API call.

To start testing this service we will create new test file and start importing the followings
1-     Create test file with name for example “networkLibraryService.test.js”
2-     We create file “.js” to implement our test.
3-     Note that file is JavaScript so you can’t use any typescript types defined on the project directly.
4-     Also, the file name should contain “.test” suffix so that it can be considered as a test file otherwise you will not find your file included in npm test files.


import * as sinon from 'sinon'
import { NetworkLibraryService } from './ NetworkLibraryService

Then we will start implement our test logic for this service to be as the following


describe('NetworkLibraryService', () => {
  describe('fetchNetworkLibraries', () => {
    let sandbox, invoke

    beforeAll(() => {
      sandbox = sinon.sandbox.create()
      invoke = sandbox.stub(NetworkLibraryService, 'invoke')
      NetworkLibraryService.fetchNetworkLibraries()
    })

    afterAll(() => {
      sandbox.restore()
    })

    it('calls invoke', () => {
      expect(invoke.getCall(0).args[0]).toEqual('GetNetworkLibraries')
    })
  })

In the code above we created our sandbox that we are going to use within the test to mock API calls
After defining our sandbox object, we will define Mock for methods we not need it to be called during the test like “invoke” method

      invoke = sandbox.stub(NetworkLibraryPackageService, 'invoke')

then we start calling the method we are testing to check the result.
In our example we need to make sure that our method is invoking 'GetNetworkLibraries' successfully.
To check this behavior, we are going to do the following

    it('calls invoke', () => {
      expect(invoke.getCall(0).args[0]).toEqual('GetNetworkLibraries')
    })

If this line failed during testing this means that our code not applying this check conditions which here validates that the first argument for the ‘invoke’ method is 'GetNetworkLibraries'

Note that in case there is other arguments sent to the method called we will need to add check for it .

expect(invoke.getCall(0).args[1]).toEqual(Other Argument2)
expect(invoke.getCall(0).args[2]).toEqual(Other Argument3)


References:
-        http://sinonjs.org/


Comments

Popular posts from this blog

Applying unit test for Redux-Saga with React and Typescript

Logging w/ MetroLog in (UWP) Application

Redux Containers Unit Testing in React with TypeScript Projects