Mock an Angular Service

When we unit test an angular controller we test it in isolation replacing​ the services that the controller uses with test doubles (aka mocks). In Jasmine, the kind of test double used is called Spy​. (Read more: http://jasmine.github.io/2.0/introduction.html)

The next code example shows the most basic beforeEach initialization block for a controller test suit. In it we use the $controller service to instantiate the controller under test MyCtrl injecting a new clean $scope before each test execution.

beforeEach(inject(function ($rootScope, $controller) {
    scope = $rootScope.$new();
 
    $controller('MyCtrl', {
        $scope: scope // inject the stubbed scope
    });
}));

During the instantiation of the controller, we can configure the mock services or stubbed data to inject. Notice that for all the dependencies that we don’t configure explicitly​ the unit test will use the real ones.
There are different ways to mock dependencies, I am going to show two alternatives here:

Replacing a service by a spy object

var stateSpy;
 
beforeEach(inject(function ($rootScope, $controller, MyService) {
    scope = $rootScope.$new();
    controller = $controller;
 
    stateSpy = jasmine.createSpyObj('$state', ['go']); // create a test double for a $state service with function called go
 
    $controller('MyCtrl', {
        $scope: scope,
        $state: stateSpy // inject the test double in the controller
    });
 
}));

Replacing the functions of a service by spies
Let’s say that MyCtrl makes use of a function getData() on a service called MyService. We can remplace that function with an spy and fake their response.

beforeEach(inject(function ($rootScope, $q, $controller, MyService) {
    scope = $rootScope.$new();
    q = $q;
    controller = $controller;
 
    spyOn(MyService, 'getData').and.callFake(function () {
        var deferred = $q.defer();
        deferred.resolve(TEST_DATA);
        return deferred.promise;
    });
 
    $controller('MyCtrl', {
        $scope: scope
    });
 
}));

With this approach, we are replacing the functions of a service,​ not the service itself. If the function to spy doesn’t exist in the service the test will fail.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s