Is it possible to mock local variable in angularjs

2019-06-02 10:35发布

问题:

I have the below code:

'use strict';

angular
    .module('testmodule')
    .factory('TestService', ['$q', '$timeout',
        function ($q, $timeout) {

var timeoutRetries = 0; // need to mock this from here

            var api = new TestApi();

            function getResults(id, prevDeferred) {
                var deferred = prevDeferred || $q.defer();

                function handleSuccessResponse(data) {
                    if (data.status === 'ready') {
                        results.put(id, data);
                        deferred.resolve(data);
                    } else {                        

if (++timeoutRetries > 30) { // It wont get in here

                            handleErrorResponse();
                        } else {
                            $timeout(function () {
                                getResults(id, deferred);
                            }, 2000);
                        }
                    }
                }

                function handleErrorResponse(response) {
                    deferred.reject(response);
                }

                if (results.get(id)) {
                    deferred.resolve(doSomething.get(id));
                    return deferred.promise;
                }

                api.get({id: id}).then(handleSuccessResponse, handleErrorResponse);
                return deferred.promise;
            }

            return {
                getResults: getResults
            };
        }]);

I am trying to mock the timeoutRetries entry from karma but i am not able to do it. Is it the ideal way of declaring it or should i want to move the variable to some function and update or which is the best way to mock it up from karma?

Tried with inject, declared the variable before calling the function. Still no success.

回答1:

You need to cover that branch so that it automatically covers local variable. Looks like your test is not covering that scenario.

You are depend on status data from results.. if it is ready you are returning results.. if not increment timeout and if it is > 30 then throw error message else poll for the results again until either you get status as ready or timeout is 30.

You can cover else branch easily.

var isReadyTrue = false;
$httpBackend.expectGET(url).respond(function () {
            return [201, function(){
if (isReadyTrue) {
results.data = 'Ready';
} else {
results.data = 'Not Ready';
}
isReadyTrue = true; // Next result will be ready..

return results;
}];
        });

We can't mock local variable, but we can mock scenario to cover that.

First result will be not Ready so timeout will be 1 and goes for polling, Next result returns with Ready data.

You can mock for timeout 30 using combination of above and $timeout