Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create unit-testing for array function in AngularJS with Jasmine

I have xf array: var xf = []; And I have a function is a element in this array and a function to use it:

$scope.checkEmailValid = function () {
  var result = false;
  Iif (xf.validateEmail($scope.email, '256')) {
    result = true;
  }
  return result;
};

xf.validateUsername = function (sText) {
  var isValid = false;
  do {
    //Check for valid string.
    isValid = typeof sText === 'string';
    if (!isValid) {
      break;
    }
    //Check that each special character does not exist in string.
    for (var i = 0; i < sText.length; i++) {
      if (xf.SPECIAL_CHARS.indexOf(sText.charAt(i)) !== -1) {
        isValid = false;
        break;
      }
    }
    if (!isValid) {
      break;
    }
  } while (false);
  return isValid;
};

But when I run my spec:

it ('checkEmail', function(){
  $controller('MyCtrl', { $scope: $scope });
  xf.validateUsername();
  spyOn(window,xf.validateUsername).and.callThrough();
});

It makes an error:

xf.validateUsername is not a function

How can I cover it?

like image 978
Pham Minh Tan Avatar asked Jul 31 '15 10:07

Pham Minh Tan


People also ask

How do you write unit test cases in Angular using Jasmine?

Create an Angular project with jasmine and karma By doing this, the jasmine and karma configuration is resolved for us. Install and create a new project with angular-cli: Install npm -g @angular/cli. Ng new angular-unit-testing angular unit-testing.

What is Jasmine testing framework and how do you use it for Angular unit testing?

Jasmine is a behavior development testing framework. Unit tests are written using Jasmine and are run to see if individual parts of an application are working correctly. As a result, unit tests will either pass or fail depending on if the code is working correctly or has a bug.


1 Answers

The xf variable is not acessible from the outside of the controller's scope (i.e. not accessible in the unit test files).

You must've done the following thing:

angular
  .module('myModule')
  .controller(function ($scope) {
    var xf = [];
    // etc.
  });

You could attach the xf variable to the MyController instance once Angular instantiates it:

angular
  .module('myModule')
  .controller(function ($scope) {
    this.xf = [];
    // etc.
  });

But that's not really a clean way of doing it. A better way (in my opinion) would be to create a factory:

angular
  .module('myModule')
  .factory('xfService', function () {
    var xf = [];

    function validateUsername(text) {
      // etc.
    }

    function get() {
      return xf;
    }

    return {
      get: get,
      validateUsername: validateUsername
    };
  });

Now, you can inject the factory in your controller to use xf:

angular
  .module('myModule')
  .controller(function ($scope, xfService) {
    // somewhere
    var isValid = xfService.validateEmail($scope.email, '256');
    // to get the values in the array
    var values = xfService.get();
  });

Finally, for the unit tests, it becomes really easy to test the validateEmail method.

describe('Unit tests - xfService', function () {
  var xfService;
  beforeEach(angular.module('myModule'));
  beforeEach(angular.inject(function (_xfService_) {
      xfService = _xfService_;
    });
  });

  describe('xfService.validateUsername', function () {
    it('should return a boolean value', function () {
      // for example
      expect(typeof xfService.validateUsername('test')).toBe('boolean');
    });
    // add more unit tests to check that the method works as expected
  });
});

You'll need to add the angular-mocks file to the Karma config.

Thanks to Paul Podlech and Claies for the hints in the comments/answers.

like image 54
Benoit Avatar answered Nov 14 '22 22:11

Benoit