0

I'm a newbie to programming and I'm trying to figure out how to unit test angularJS code with jasmine, and its driving me insane!

This is the angular code im trying to test, its all set up on an asp.net web application using abpBoilerplate and angular. The result of the code below is that when a button is clicked on the web page, a 'success' popup appears and "true" appears in a text box, if the service is available. The service is being pulled from classes within a web api project.

(function() {
    var controllerId = 'app.views.home';
    angular.module('app').controller(controllerId, [
        '$scope', 'abp.services.lfcservice.webapi', function($scope,lfcServices) {
            var vm = this;

            //Home logic...

            vm.CheckLfcIsAvailable = function () {
                lfcServices.lfcIsAvailable()
                    .success(function () {
                        abp.notify.info('Success');
                        vm.Available = 'True';
                    });
                };

I just need to know how to write a jasmine test that passes when it expects a true value for the lfc service. Ive tried loads of different combinations with no success, I could paste in 10 different attempts ive had in here but they are all very different.

Any help would be much appreciated!

taxer03
  • 63
  • 2
  • 5

1 Answers1

1

First, you need to know how to test a controller, mocking the service. Then, you need to mock the service API to return a promise.

let's say thet the controller is initiated with Available = false;.

Test an angular 1.x controller (see jsFiddle):

describe("app.views.home controller spec", function() {
    var ctrl;
    //depend on the module
    beforeEach(module('app'));

    beforeEach(inject(function($controller) {
        //use angular's "$controller" to get the controller
        ctrl = $controller("app.views.home");
    }));

    it("available should be false", function() {
        expect(ctrl.Available).toBe(false);
    });  
});

Now, let's asume that the service returns a simple result (without promises) and see how do we provide a mock service instead of the real service.

Test an angular 1.x controller with mock service (see jsFiddle):

beforeEach(module(function($provide) {
    var mockService = jasmine.createSpyObj('mock', ['lfcIsAvailable']);
    mockService.lfcIsAvailable.and.returnValue(true);
    $provide.value('abp.services.lfcservice.webapi', mockService);
}));

Now, let's see how to mock a promise response. for this we will use $q.

Mock angular 1.x promise (see jsFiddle):

it('should change after promise resolved', inject(function($q, $rootScope) {
    //create promise
    var deferred = $q.defer();

    //mock service response 
    mockService.lfcIsAvailable.and.returnValue(deferred.promise);

    //call CheckLfcIsAvailable ()
    ctrl.CheckLfcIsAvailable ();

    expect(ctrl.Available).toBe(false);

    deferred.resolve(true);

    //not yet...
    expect(ctrl.Available).toBeNull(false);

    //from angular $q documentation: 
    //"it's important to know that the resolution of promises is tied to the digest cycle"
    $rootScope.$apply();

    //now!
    expect(ctrl.Available).toBe(true);

}));
ronapelbaum
  • 1,617
  • 14
  • 19