Filosssof
Filosssof

Reputation: 1358

Testing angular service with Jasmine

I have to test a service with local variables some of methods which do not use local variables pass ok, but some of them fall because the variable is undefined in service scope. Here is my code:

(function() {
    'use strict';

    angular.module('app').service('CalculatorService', CalculatorService);

    function CalculatorService() {

        return {
            insertValue : insertValue,
            equals : equals,
            eraseNumber : eraseNumber,
            makeOperation : makeOperation
        }

        var prevValue = 0;
        var operation = '';
        var nextNumber = false;

        function insertValue(digit, display) {
            console.log("prevValue is: " + prevValue);
            if (display === 0 || nextNumber) {
                prevValue = display;
                display = digit;
                nextNumber = false;
            } else {
                display = display + '' + digit;
            }
            return display;
        }

        function equals(display,direct) {
            if (operation === 'plus') {
                display = parseInt(prevValue) + parseInt(display);
            }

            if (operation === 'minus') {
                display = prevValue - display;
            }

            if (operation === 'mult') {
                display = prevValue * display;
            }

            if (operation === 'divide') {
                if (display === 0) {
                    display = 'Divide by 0';
                }else{
                    display = prevValue / display;  
                }

            }
            nextNumber = true;
            prevValue = display;
            if(direct){
                operation='';
            }


            return display;
        }

        function makeOperation(val, display) {
            var firstTime = (operation==='' || operation===undefined);
            var result = equals(display,false)
            operation = val;
            nextNumber = true;
            if(firstTime){
                return display;
            }else{
                return result;
            }

        }

        function eraseNumber(display) {
            display = 0;
            operation = '';
            return display;
        }
    }
})();

and this is my test:

(function(){
    'use strict';

    describe('Service: CalculatorService', function() {
        beforeEach(module('app'));

        var mockDisplay = 0;

        it('should change display from 0 to 5', inject(function(CalculatorService) {
            mockDisplay = CalculatorService.insertValue(5,mockDisplay);
            expect(parseInt(mockDisplay)).toEqual(5);

        }));

        it('should change display from 5 to 55', inject(function(CalculatorService) {
            mockDisplay = CalculatorService.insertValue(5,mockDisplay);
            expect(parseInt(mockDisplay)).toEqual(55);
        }));


        it('should not change display (55)', inject(function(CalculatorService) {
            mockDisplay = CalculatorService.makeOperation('divide',mockDisplay);
            expect(parseInt(mockDisplay)).toEqual(55);
        }));

        it('should change display from 55 to 5', inject(function(CalculatorService) {
            mockDisplay = CalculatorService.insertValue(5,mockDisplay);
            expect(parseInt(mockDisplay)).toEqual(5);
        }));




    });
})();

How can I test this service?

Upvotes: 0

Views: 50

Answers (1)

Estus Flask
Estus Flask

Reputation: 222309

It should be

    var prevValue = 0;
    var operation = '';
    var nextNumber = false;

    return {
        insertValue : insertValue,
        equals : equals,
        eraseNumber : eraseNumber,
        makeOperation : makeOperation
    }

Local variables are hoisted, and early return causes them to be undefined.

The dependency on local variables ceases to be a problem when they are exposed as private properties that reflect the internal state of the service and can be mocked or verified.

var obj = {
    _prevValue: 0,
    _operation: '',
    _nextNumber: false,
    ...
};

return obj;

Upvotes: 1

Related Questions