Search code examples
javascriptangularjsunit-testingjasminehottowel

mock a function call using jasmine


Getting started with HotTowelAngular template and I'm setting up unit testing. Ran into a snag.

I'm trying to test a function in my controller that happens to call another function named "log". This "log" is a function stored in a private variable which gets its value from a dependency called "common".

I'm aware that I probably need to stub this function in some way, but I'm unsure of where to start for this particular example, as I'm pretty new to angularjs, jasmine, et all. Any ideas are appreciated

unit test:

describe("quote", function () {
    var scope,
        controller,
        common;

    beforeEach(inject(function($rootScope, $controller, _common_) {
        scope = $rootScope.$new();
        common = _common_;
        controller = $controller;
    }));

 describe("removeAttachment", function() {

        it("should remove the attachment when requested", function() {
            var vm = controller("quote", { $scope: scope });

            vm.attachmentList.push({ FileName: "file1", FileAsString: "..." });
            vm.attachmentList.push({ FileName: "file2", FileAsString: "..." });
            vm.attachmentList.push({ FileName: "file3", FileAsString: "..." });
            expect(vm.attachmentList.length).toEqual(3);

            // here's the call where it fails
            vm.removeAttachment(vm.attachmentList[1]);

            expect(vm.attachmentListCount).toEqual(2);
            expect(vm.attachmentList.length).toEqual(2);
            expect(vm.attachmentList[1].FileName).toBe("file3");
        });
    });
 });

controller:

 var getLogFn = common.logger.getLogFn;
 var log = getLogFn(controllerId);

 function removeAttachment(attachment) {

        // need to stub this out
        log('removing attachment: ' + attachment.FileName);

        vm.attachmentList.splice(vm.attachmentList.indexOf(attachment), 1);
        vm.attachmentListCount = vm.attachmentList.length;
    }

The error from Jasmine:

TypeError: 'undefined' is not a function (evaluating 'log('removing attachment: ' + attachment.FileName)')


Solution

  • In your test you should have controller = $contoller("YourController", {it's dependencies});

    You probably don't want to pass in your common service, but create a stub that returns a function.

    var  wrapper = {logger: function () {}};
    var stub = { logger: { getLogFun: function() {return wrapper.logger} }};
    

    You can pass that in place of your common service.

    You can now spy on it with:

    spyOn(wrapper, 'logger');