Jasmine spyOn 使用伪造的 return 数组测试功能

Jasmine spyOn testing functionality with faked return array

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

我知道我使用 spyOn().and.returnValue() 来伪造 return 数组。但是我如何使用那个假 return 测试函数的重新排序功能?特别是如何在规范中引用伪造的 return?

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

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);
    });
});

Plunkr