r.bhardwaj
r.bhardwaj

Reputation: 1613

mock angularjs service for unit testing using jasmine

I have an Angular App and I want to create unit test cases for it using jasmine.
In my AngularJS app, I have a service as :

var canceler;
var myServices = angular.module('myServices', ['ngResource'])

myServices.factory('getData', ['$http', '$q', function($http, $q){
    var canceler;
    return {
        setData: function(url, callback, error) {
                    canceler = $q.defer();
                    $http.post(url, {}, {timeout:canceler.promise}).success(callback).error(error);
        },
        abort: function(){ canceler.resolve();}
    }
}]);

This service is being used by controller.

Now how can I provide a mock for this "getData" service to the injector I am using in controllerSpecs.js (for the unit testing using jasmine).

For the reference, the code of controllerSpecs.js is defined in Getting error while using Jasmine with AngularJS.

Upvotes: 7

Views: 12665

Answers (2)

IgorCh
IgorCh

Reputation: 2661

Try something like this

//creation mock service
var mockGetData = {
  data: [],
  setData: function(url, callback, error){
    //emulate real work, any logic can be here
    data.push('called');
    callback(data);
  }
}

and use of the mock service

it('test description', inject(function ($rootScope, $controller){
  var scope = $rootScope.$new();
  var ctrl = $controller('TodoController', { $scope: scope, getData: mockGetData });
  //some test here....
}))

Upvotes: 2

jelinson
jelinson

Reputation: 845

You can use AngularJS's $provide service. This page demonstrates how to mock the functionality of a service using Jasmine's spies. Basically in your Jasmine test you can include:

var getDataMock;

beforeEach(function() {
  getDataMock = {
    setData: jasmine.createSpy(), 
    abort: jasmine.createSpy()
  };

  module(function($provide) {
    $provide.value('getData', getDataMock);
  });
});

This tells AngularJS that instead of using the real getData service, the mock will be used in its place. In this example, using a Jasmine spy for the mock lets you easily create expectations about how and when the getData service is called by the controller. You can alternatively set getDataMock to any other object, though it makes sense to support the same API as the real getData service.

For bonus points, you can specify the getDataMock object in a separate file, so that the mock may be easily used in any number of unit tests where the thing being tested uses getData. This however requires some configuration with whatever Jasmine runner you are using.

This is all assuming you wish to unit test the controller. If you want to unit test the getData service itself, AngularJS provides a nice mocking utility specifically for http requests.

Upvotes: 11

Related Questions