lundi 21 décembre 2015

Fake $resource $save function in angularjs jasmine controller unit test

I'm writing unit tests for angularjs using jasmine framework. There is a userService which is used by the controller and which I need to fake. I know that I can use jasmine's spyOn functionality, but I've decided to go with different approach (fake the whole service). Problem is that I cannot correctly fake $save function and controller doesn't see it.

I'm including only relevant bits of code.

Here's real UserService which uses $resource

    userService.factory("UserService", ["$resource",
    function($resource) {

        var api = "api/AdminApi/";

        return $resource(

            // default api
            api + ":id",

            // custom actions
            {
                GetGroups: {
                    url: api + "GetGroups",
                    method: "GET",
                    isArray: true
                }
            });
    }

Here's the fake mocked service:

var mockUserService = {

// get
query: function() {
    return this._users;
},

// post
$save: function (user) {        // SOMETHING WRONG IN THIS FUNCTION?
    var deferred = $q.defer();
    deferred.resolve(user);
    return deferred.promise;
},

GetGroups: function() {
    return this._groups;
},

// these are "private".
_users: [],
_groups: [],
_loggedInUser: {},
$q: null, ...

Here's test code

var $scope;
beforeEach( function() {

    module("adminApp", function ($provide) {
    });

    inject(function ($controller, $rootScope, $q) {

        $scope = $rootScope.$new();  
        $controller("GroupController", {
            $scope:         $scope,
            UserService:    mockUserService.Initialize($q)
        });

        // resolve promises   
        $scope.$digest();
    });
});

describe("test.", function () {

    describe("Groups.", function () {

        it("Should add user to administators group", function () {

            var testUser = getUserByName($scope.Users, "JustUser");
            var administratorsGroup = getGroupByName($scope.Groups, "Administrators");
            expect(userHasGroup(testUser, administratorsGroup)).toBeFalsy();

            $scope.SelectGroup(1, administratorsGroup); // first we should select group
            $scope.ToggleGroupForUser(testUser);

            expect(userHasGroup(testUser, administratorsGroup)).toBeThuthy();

        });
    });

A part of controller code that fails. Message: TypeError: undefined is not a constructor (evaluating 'userCopy.$save'). For some reason $save function is not being faked correctly as controller doesn't see it in mockUserService.

var userCopy = angular.copy(user);

            if (userHasGroup(user, $scope.SelectedGroup)) {
                deleteGroupFromUser(userCopy, $scope.SelectedGroup);

            } else {
                userCopy.Groups.push($scope.SelectedGroup);
            }

            $scope.UserPromise = userCopy.$save( // CODE FAILS ON THIS LINE, probably because $save function is not faked correctly 
                function() {

                    substituteUserByUpdatedVersion(userCopy);
                    updateUserList();
                },
                function() {
                    alert("error");
                });

I'm using angular 1.4.8 and jasmine 2.4.1. Thanks in advance

Aucun commentaire:

Enregistrer un commentaire