[英]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();
});
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.