17th Nov 2017

AngularJs with Jest Unit Testing

AngularJs with Jest

Jest, a unit testing framework by Facebook, is commonly associated with the React JS library. However Jest is not specifically for React, and can be used to test any javascript code you wish.

Recently I've been using Jest with AngularJs 1.6 and have put together the following step-by-step guide on how to get setup.

This guide includes:

  • Installing Angular Mocks and Jest CLI
  • Creating an AngularJs Service
  • Create Jest unit test file
  • Running Jest tests with failed example
  • Correcting service and running successful Jest tests
  • Checking code coverage of tests
  • TL;DR - Full Working Example on GitHub

Install Angular Mocks and Jest CLI

To use Jest with AngularJs you will require the Angular Mocks and Jest CLI packages, which can be installed using npm:

npm i angular-mocks --save-dev
npm i jest-cli --save-dev

In your package.json file the test script can then be set to jest:

"scripts": {
  "test": "jest"
},

Create AngularJs Service

For the purpose of this example I've created a simple module with a service that does some basic calculations.

For now I've left out the logic within the functions to show that these tests fail.

Create Jest unit test file

Next we'll create the unit test file for testing our AngularJs service.

In this file we:

  • Require the files needed for the test. This includes the AngularJs framework, Angular Mocks and the actual service we're testing, mathservice.js.
require('../node_modules/angular/angular.min.js');
require('../node_modules/angular-mocks/angular-mocks.js');
require('./mathservice.js');
  • Create a describe function which will group our tests together in the same block. In this instance the block is for testing the addTwoNumbers function specifically.
describe('Math service - addTwoNumbers', function(){
  • Mock the AngularJs module and inject the service. This will load the module and service so that we are able to reference the service to call the function.
beforeEach(
  angular.mock.module('mathmodule')
);

var _mathservice;

beforeEach(inject((mathservice) => {
  _mathservice = mathservice;
}));
  • Set up several tests to ensure we receive the expected output from the function. Individual tests are set up by calling the it function. Each it function then calls the addTwoNumbers function and compares the actual result with the expected result by calling expect.
it('1 + 1 should equal 2', function(){
  var actual = _mathservice.addTwoNumbers(1,1);
  expect(actual).toEqual(2);
});

Run the tests and see the failed output

Run npm test and you should see the following output:

Jest Fail Output

Add logic to the service and re-run the tests

Now if we update our service with the correct logic and re-run the tests we should see them all pass:

Jest Pass Output

Code Coverage

Jest also has the ability to show code coverage across the JS files within the application.

This can be shown by running jest --coverage:

"scripts": {
  "test": "jest --coverage"
},

Jest Code Coverage

Now if we add an additional function to the Math Service without any tests then the code coverage report will show a reduced percentage and flag which lines of code are not being covered.

angular.module('mathmodule', [])
  .factory('mathservice', function(){

    var addTwoNumbers = function(x, y){
      return x + y;
    };

    var multiplyTwoNumbers = function(x, y){
      return x * y;
    };

    return {
      addTwoNumbers,
      multiplyTwoNumbers
    };
  });

Jest Code Coverage Failure

Testing services with dependencies

If the service has a dependency itself, then this dependency will need to be mocked. For example if the mathservice example was being consumed by another service, then that service would mock mathservice like so:

  beforeEach(function(){

    angular.module('mathmodule', []);
    angular.mock.module('mymodule');

    angular.mock.module(function($provide) {
      $provide.service('mathservice', function(){
        return {
          addTwoNumbers: function(x,y){
            return x+y;
          }
        }
      });
    });

  });

Full Working example

A full working example of this is available on GitHub:

https://github.com/curtiscde/angularjs-jest-example