簡體   English   中英

如何測試角度$ cacheFactory?

[英]How to test angular $cacheFactory?

我在有角度的服務中使用$ resource。 我想使用基於$ cacheFactory的自定義緩存,而不是內置的$ http緩存,以便當響應從我的REST服務返回時可以操縱該緩存。

在模擬單元測試中模擬$ cacheFactory時,我遇到了很大的困難,有人可以幫助我為測試定義正確的模擬和設置嗎?

這是我要測試的代碼的簡化版本。 注意,我告訴我的角度應用在myApp.run()使用我的自定義緩存'DefaultCache'代替它將使用的默認$http緩存。 (我知道這是為所有$ resource服務替換默認緩存的方法)。

編碼

var myServices = angular.module('myServices', ['ngResource']);

var myApp = angular.module('myApp', [
    'myServices'
]);

myApp.run([
    '$http',
    '$cacheFactory',
    function ($http, $cacheFactory) {
        // Replace default $http cache with one we can control
        $http.defaults.cache = $cacheFactory('defaultCache');
    }]);

myServices.factory('MyService', [
    '$resource',
    '$cacheFactory',
    function($resource, $cacheFactory) {

        var cache = $cacheFactory.get('defaultCache');

        function doSomething(data) {
            var cached = cache.get('akey');
            return angular.fromJson(data);
        }

        return {
            things: $resource('/api/things/:id', { id: '@id' }, {
                query: {
                    method: 'GET',
                    isArray: true,
                    cache: true,
                    transformResponse: function(data) {
                        return doSomething(data);
                    },
                },
            })
        }
    }]);

考試

這是我的測試設置。 (注意:提供的mockCacheFactory返回一個對象):

///<reference path="~/Scripts/jasminejs/jasmine.js"/>
///<reference path="../../Web/Scripts/angularjs/angular.js"/>
///<reference path="../../Web/Scripts/angularjs/angular-mocks.js"/>
///<reference path="../../Web/Scripts/angularjs/angular-resource.js"/>

describe("MyServiceSpec", function () {

    beforeEach(module('myServices'));

    describe('GivenThingsResource', function () {

        var $httpBackend, MyService, mockCacheFactory;

        beforeEach(module(function ($provide) {
            mockCacheFactory = {
                get: function (cacheName) {
                    return {
                        get: function (key) { },
                        put: function (key, value) { },
                    };
                },
            };

            $provide.value('$cacheFactory', mockCacheFactory);
        }));

        beforeEach(inject(function (_$httpBackend_, _MyService_) {
            $httpBackend = _$httpBackend_;

            MyService = _MyService_;

            spyOn(mockCacheFactory, 'get').andCallThrough();
        }));

        it("WhenQuery_ThenReturnsData", function () {
            $httpBackend.expectGET('/api/things').respond(JSON.stringify({ Things: [{ Id: '1' }, { Id: '2' }] }));
            var result = MyService.things.query();
            $httpBackend.flush();

            expect(result).toEqualData({ Things: [{ Id: '1' }, { Id: '2' }] });
        });

    });
});

檢測結果:

我看到的問題是:運行測試時,出現以下兩個錯誤:

TypeError: 'undefined' is not an object (evaluating '$httpBackend.expectGET') in http://localhost:35050/Tests.js (line 76)
TypeError: 'undefined' is not an object (evaluating '$httpBackend.expectGET')
    at  TestSpec.js: line 76
    at   jasmine.js: line 1064
    at   jasmine.js: line 2096
    at   jasmine.js: line 2086TypeError: '[object Object]' is not a function (evaluating '$cacheFactory('$http')')
TypeError: '[object Object]' is not a function (evaluating '$cacheFactory('$http')')
    at   angular.js: line 7527
    at invoke (  angular.js: line 3966)
    at   angular.js: line 3808
    at getService (  angular.js: line 3930)
    at invoke (  angular.js: line 3957)
    at   angular.js: line 3808
    at getService (  angular.js: line 3930)
    at invoke (  angular.js: line 3957)
    at   angular.js: line 3808
    at getService (  angular.js: line 3930)
    at invoke (  angular.js: line 3957)
    at workFn (  angular-mocks.js: line 2161)
    at   jasmine.js: line 1064
    at   jasmine.js: line 2096
    at   jasmine.js: line 2086
undefined

因此,我認為我的模擬是錯誤的,因此我將提供的mockCacheFactory更改為一個函數,以便對$cacheFactory('$http')的調用應成功:

mockCacheFactory = function () {
    return {
        get: function (cacheName) {
            return {
                get: function (key) { },
                put: function (key, value) { },
            };
        },
    };
};

但是我現在得到這些錯誤:

TypeError: 'undefined' is not a function (evaluating '$cacheFactory.get('defaultCache')')
TypeError: 'undefined' is not a function (evaluating '$cacheFactory.get('defaultCache')')
    at  TestSpec.js: line 25
    at invoke (  angular.js: line 3966)
    at   angular.js: line 3808
    at getService (  angular.js: line 3930)
    at invoke (  angular.js: line 3957)
    at workFn (  angular-mocks.js: line 2161)
    at   jasmine.js: line 1064
    at   jasmine.js: line 2096
    at   jasmine.js: line 2086
undefinedTypeError: 'undefined' is not an object (evaluating '$httpBackend.expectGET') in http://localhost:40529/Tests.js (line 78)
TypeError: 'undefined' is not an object (evaluating '$httpBackend.expectGET')
    at  TestSpec.js: line 78
    at   jasmine.js: line 1064
    at   jasmine.js: line 2096
    at   jasmine.js: line 2086

請幫助

我真的不明白在我的模擬中需要什么來滿足使用模擬的代碼。 它似乎需要具有一些JavaScript對偶性,而我在模擬的定義中不知道該如何模仿。

有人知道我的模擬應該如何構造嗎? 或者我在這里還想念什么?

今天,我在同一個問題上苦苦掙扎,並找到了解決此問題的不同解決方案。 (角度1.3.13)

顯然,$ cacheFactory有一個get方法,因此您可以檢索cacheId的實例。 這將使您能夠監視正確的緩存實例。

beforeEach(inject(function (_$cacheFactory_) {
  mockCache = _$cacheFactory_.get('defaultCache');
}));

it('your test', function () {
  spyOn(mockCache, 'get').andCallThrough();
  ....
  expect(mockCache.get).toHaveBeenCalledWith('akey'); 
});

對於以后遇到相同問題的任何人。

我沒有找到構建適用於此代碼的模擬的方法。 我什至接受了$ cacheFactory的實現(來自github),剝離了它的實現,並嘗試將其用作模擬,並將其插入測試中。 那里也沒有運氣。

但是,我確實遇到了一個隨機帖子,該帖子暗示也許我應該創建自己的緩存服務(在我自己的服務中),這將使用$ cacheFactory創建緩存。 然后,我可以將我的緩存服務注入到資源中(對於服務來說是正常的),而不是直接使用$ cacheFactory。 模擬該緩存服務應該很簡單。

我做到了,現在還好。

我的新緩存服務:

myServices.factory('ServiceCachingService', [
    '$cacheFactory',
    function (
        $cacheFactory
        ) {
        return $cacheFactory('defaultCache');
    }]);

新的app.run():

myApp.run([
    '$http',
    'ServiceCachingService',
    function ($http, ServiceCachingService) {
        // Replace default $http cache with one we can control
        $http.defaults.cache = ServiceCachingService;
    }]);

我的新數據服務:

myServices.factory('MyService', [
    '$resource',
    'ServiceCachingService',
    function($resource, ServiceCachingService) {

        function doSomething(data) {
            var cached = ServiceCachingService.get('akey');
            return angular.fromJson(data);
        }

        return {
            things: $resource('/api/things/:id', { id: '@id' }, {
                query: {
                    method: 'GET',
                    isArray: true,
                    cache: true,
                    transformResponse: function(data) {
                        return doSomething(data);
                    },
                },
            })
        }
    }]);

然后是新的測試模型:

mockCachingService = {
    get: function (key) {},
    put: function (key, value) { },
};

以下代碼將允許您在單元測試中模擬$ cacheFactory。 $ provide服務將允許服務依賴項注入使用$ cacheFactory而不是默認的$ cacheFactory。

var cache, $cacheFactory; //used in your its
beforeEach(function(){
    module(function ($provide) {
        $cacheFactory = function(){};
        $cacheFactory.get = function(){};

        cache = {
            removeAll: function (){}
            //add other methods here
        };
        spyOn(cache, 'removeAll');
        spyOn($cacheFactory, 'get').and.returnValue(cache);

        $provide.value('$cacheFactory', $cacheFactory);
    });
});

describe('yourFunction', function(){
    it('calls cache.remove()', function(){
        yourService.yourFunction();
        expect(cache.remove).toHaveBeenCalled();
    });
});

https://stackoverflow.com/a/29426640/1270786

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM