如何模拟服务中存在的函数?

时间:2017-03-07 08:53:16

标签: javascript angularjs unit-testing jasmine

我试图模拟一个返回promise的服务中存在的函数。

testService.js

describe('Service: ingredientsNames', function () {

var mock = null,
    backendReady = null,
    namesEndpoint = {execute: function() {}},
    ingredientsNames = null,
    $rootScope
;

beforeEach(module('aWareAdmin'));

beforeEach(function() {
    mock = {
        ready: null,
        admin: {
            ingredients: {
                names: function (request) {
                    return namesEndpoint;
                }
            }
        },
        execute: namesEndpoint.execute
    };

    module(function($provide) {
        $provide.value('aWare', mock);
    });

    inject(function($injector) {
        var $q = $injector.get('$q');
        $rootScope = $injector.get('$rootScope');

        backendReady = $q.defer();

        mock.ready = backendReady.promise;

        ingredientsNames = $injector.get('ingredientsNames');
    });
});

it('should retrieve a list of ingredients names from backend', function() {
    backendReady.resolve('ready');

    namesEndpoint.execute = function(callback) {
        callback({names: []});
    };

    ingredientsNames.fetch();
    $rootScope.$digest();

    expect(ingredientsNames.getNames()).toBeDefined();
    expect(ingredientsNames.getNames()).toEqual([]);
});

service.js

angular.module('aWareAdmin')
  .service('ingredientsNames', [
    'aWare',
    '$q',
    '$log',
    'env',
function(
    aware,
    $q,
    $log,
    env
) {
    var names = [],
        msg = {
            cursor: null,
            size: 100
        },
        requestSent = false,
        hasMore = true,
        self = this,
        defaultLanguage = {
            code: 'nc',
            name: 'Default (INCI)'
        }
    ;

    // Recursive function for getting ingredients names
    this.fetch = function() {
        var deferred = $q.defer();

        if (requestSent) {
            return deferred.promise;
        }

        if (!hasMore) {
            deferred.resolve(names);

            return deferred.promise;
        }

        if (!env.isProduction()) {
            msg.size = 20;
        }

        aware.execute('admin.ingredients.names', msg).then(function(response) {
            if (response.names) {
                $log.info('Received Ingredients Names: ', response.names);
                angular.forEach(response.names, function(name) {
                    this.push(name);
                }, names);

                msg.cursor = response.cursor;

                hasMore = response.more;

                deferred.resolve(response.names);
            } else {
                $log.debug('Ingredients Names API not sending names: ', response);

                hasMore = response.more;

                deferred.reject('No items were received.');
            }

            requestSent = false;

            if (hasMore && env.isProduction()) {
                self.fetch();
            }
        }, function (error) {
            $log.debug('Error: fetch ingredients names!', error);
        });

        requestSent = true;

        return deferred.promise;
    };

    // Return ingredients names
    this.getNames = function() {
        return names;
    };

它会抛出错误,

PhantomJS 2.1.1 (Linux 0.0.0) Service: ingredientsNames should return the cached list of ingredients names and retrieve more FAILED
    TypeError: undefined is not a function (evaluating 'mock.callback({names: []})') in test/spec/services/ingredientsnames.js (line 218)
    execute@test/spec/services/ingredientsnames.js:218:26
    fetch@app/scripts/services/ingredientsnames.js:54:22
    test/spec/services/ingredientsnames.js:239:31
PhantomJS 2.1.1 (Linux 0.0.0): Executed 127 of 168 (34 FAILED) (0 secs / 22.615 sePhantomJS 2.1.1 (Linux 0.0.0): Executed 128 of 168 (34 FAILED) (0 secs / 22.618 sePhantomJS 2.1.1 (Linux 0.0.0): Executed 129 of 168 (34 FAILED) (0 secs / 22.621 sePhantomJS 2.1.1 (Linux 0.0.0): Executed 130 of 168 (34 FAILED) (0 secs / 22.626 sePhantomJS 2.1.1 (Linux 0.0.0) Service: ingredientsNames #remove should remove identifiers of the given ingredient FAILED
    TypeError: admin.ingredients.names is not a function (evaluating 'callback({names: namesList[0], cursor: 'c1'})') in test/spec/services/ingredientsnames.js (line 236)
    execute@test/spec/services/ingredientsnames.js:236:21
    fetch@app/scripts/services/ingredientsnames.js:54:22
    test/spec/services/ingredientsnames.js:317:35

我实际上想要模拟aware.execute函数,该函数必须在调用{{1}时返回names(由namesEndpoint.execute 设置的) }

0 个答案:

没有答案