Javascript Jasmine spyOn使用伪造返回阵列测试功能

Javascript Jasmine spyOn使用伪造返回阵列测试功能,javascript,angularjs,unit-testing,jasmine,Javascript,Angularjs,Unit Testing,Jasmine,我试图用Jasmine测试的函数获取一个对象数组,然后使用splice()方法根据函数传递的参数对其重新排序 我知道我使用了spyOn()和.returnValue()来伪造返回数组。但是如何使用这个假返回测试函数的重新排序功能呢?特别是如何在规范中引用伪造的退货 注意:重新排序后,将调用其他函数。我想在重新排序继续之前捕获其结果 function templates($rootScope, $q) { return { reorder: function(item, f

我试图用Jasmine测试的函数获取一个对象数组,然后使用
splice()
方法根据函数传递的参数对其重新排序

我知道我使用了
spyOn()和.returnValue()
来伪造返回数组。但是如何使用这个假返回测试函数的重新排序功能呢?特别是如何在规范中引用伪造的退货

注意:重新排序后,将调用其他函数。我想在重新排序继续之前捕获其结果

function templates($rootScope, $q) {
    return {
        reorder: function(item, fromIndex, toIndex) {
            var storeDeferred = $q.defer();
            $rootScope.store.templates.all(function(templates) {
                if (templates) {
                    // Reorder templates
                    templates.splice(fromIndex, 1);
                    templates.splice(toIndex, 0, item);
                    // Nuke then insert back reordered
                    this.nuke(function() {
                        this.batch(templates, function(templates) {
                            storeDeferred.resolve(templates);
                        });
                    });
                } else {
                    storeDeferred.reject('templates not found');
                }
            });
            return storeDeferred.promise;
        }
    }
}
测试

describe('Unit: templates', function() {
    beforeEach(function() {
        module('app');
        inject(function($injector) {...}); // inject Templates and $rootScope
    });

    describe('Templates.reorder', function() {
        it('should move object at index 2 to the start', function() {
            spyOn(rootScope.store.templates, 'all').and.returnValue([{a: 1}, {a: 2}, {a:3}]);
            Templates.reorder({a:3}, 2, 0);
            expect(REFERENCE_THE_FAKE_RETURN).toBe([{a:3}, {a: 1}, {a: 2}]);
        });
    });
});

您需要设置all函数以接受回调,然后使用需要测试的数组调用回调。然后,您需要使用一个变量来存储传递到所返回承诺中的模板。之后,您需要调用$digest(),然后可以使用
angular.equals
比较这些值。为了模拟单元测试中的
this
,可以使用
bind
函数将
this
设置为模拟

describe('Templates.reorder', function() {
    it('should move object at index 2 to the start', function() {
        var templatesFromPromise;
        rootScope.store = {
            templates: {
                all: function(callback) {
                    var thisMock = {
                      nuke: function (nukeCallback) {
                          var nukeCallbackBound = nukeCallback.bind(thisMock);

                          nukeCallbackBound();
                      },
                      batch: function (data, batchCallback) {
                          batchCallback(data);
                      } 
                    };

                    var callbackBound = callback.bind(thisMock);

                    callbackBound([{a: 1}, {a: 2}, {a: 3}]);
                }
            }
        };

        spyOn(rootScope.store.templates, 'all').and.callThrough();
        Templates.reorder({a:3}, 2, 0).then(function (data) {
            templatesFromPromise = data;
        });

        rootScope.$digest();

        expect(angular.equals(templatesFromPromise, [{a:3}, {a: 1}, {a: 2}])).toBe(true);
    });
});

谢谢您的解释。测试现在抱怨后面的
nuke()
函数未定义。那么,我是否在该函数上设置了间谍?如果是这样,我如何引用使用
this
调用它的事实?您是否可以设置Plunkr?我在测试代码时遇到了困难,所以我不得不即兴创作。下面是添加了您的解决方案的示例-在
nuke()
函数上失败。我可以看到它在您的plunkr中正常工作。然而,当在我的代码中实现时,我得到一个错误:
'undefined'不是一个函数(计算'callback.bind(thisMock)')
。即使复制整个
descripe
块也会产生该错误。你知道它如何在plunkr中工作,而不是在我自己的环境中工作吗?你的环境中有什么?你在使用因果报应吗?