我整个下午都在尝试为正常工作的服务编写单元测试,但没有成功。问题来自注入的依赖项,因为我有另一个服务通过单元测试(它没有依赖项)。
服务就是这个
import angular from 'angular';
export class IPMAService {
/*@ngInject*/
constructor($http, localStorageService, appConfig, locationStorageKey) {
debugger;
this.$http = $http;
this.localStorage = localStorageService;
this.appConfig = appConfig;
this.locationStorageKey = locationStorageKey;
if (Object.keys(this.localStorage.get(locationStorageKey)).length < 1) {
console.log("IPMAService - Initialization (locations not present in local storage)");
this._getLocationsFromService();
}
}
getLocations() {
console.log("IPMAService - Get Locations");
var locations = this.localStorage.get(this.locationStorageKey);
if(!locations){
return this._getLocationsFromService();
}
return locations;
};
_getLocationsFromService(){
var _self = this;
this.$http({
method: 'GET',
url: this.appConfig.ipmaWebServices.locations
}).then((response) => {
_self.localStorage.set(_self.locationStorageKey, response.data);
console.log("IPMAService - Saved locations.json to local storage with key: " + _self.locationStorageKey);
return response;
})
.catch((response) => {
console.log("IPMAService - Erro no acesso à api do IPMA: " + _self.appConfig.ipmaWebServices.locations);
})
}
}
export default angular.module('services.ipmaService', [])
.service('ipmaService', IPMAService)
.name;
&#13;
我阅读了很多关于单元测试的内容,但我似乎无法让它发挥作用。这是我的最后一次尝试(甚至不是基本的.toBeDefined(),因为它在inject函数中崩溃了:&#34; TypeError:无法将undefined或null转换为object&#34;):
'use strict';
import serviceModule from './IPMAService.service';
import LocalStorageModule from 'angular-local-storage';
import constantsModule from '../../app/app.constants';
describe('Service: IPMAService', function () {
beforeEach(angular.mock.module(serviceModule));
beforeEach(angular.mock.module(LocalStorageModule));
beforeEach(angular.mock.module(constantsModule));
var localStorageService2, service, httpBackend, ipmawebservices, locationStoreKey2;
beforeEach(inject(function (ipmaService, _$http_, localStorageService, appConfig, locationStoreKey) {
service = ipmaService;
httpBackend = _$http_;
localStorageService2 = localStorageService;
ipmawebservices = appConfig;
locationStoreKey2 = locationStorageKey;
}));
it ('should be loaded', function() {
expect(service).toBeDefined();
});
});
&#13;
另外......在我通过/工作这个基本测试后,我想知道如何测试 getLocations 方法,因为它依赖于 _getLocationsFromService 方法和 localStorage (我想我必须使用茉莉花的SpyOn,但有点帮助会很棒)。
提前致谢。
修改
这是我最后的解决方案,混合了已接受的答案和更多的研究。希望它可以帮助将来对单元测试感到绝望的人。
注意:我从服务
中删除了locationStorageKey依赖项
'use strict';
import serviceModule, { IPMAService } from './IPMAService.service';
import LocalStorageModule from 'angular-local-storage';
import constantsModule from '../../app/app.constants';
describe('Service: IPMAService', function () {
var mockDependency, appConfigDependency, service,
locationsObject = [{ local: "Lisboa", latitude: 33, longitude: 10 },{ local: "Porto", latitude: 36, longitude: 9 }];
beforeEach(angular.mock.module(serviceModule));
beforeEach(function () {
mockDependency = {
get: function () {
return locationsObject;
}
};
appConfigDependency = {
};
angular.mock.module(function ($provide) {
$provide.value('localStorageService', mockDependency);
});
angular.mock.module(function ($provide) {
$provide.constant('appConfig', appConfigDependency);
});
});
beforeEach(() => {
spyOn(IPMAService.prototype, '_getLocationsFromService').and.returnValue(locationsObject);
});
it('should return location object', inject(function (ipmaService) {
expect(ipmaService.getLocations()).toBe(locationsObject);
}));
});
&#13;
答案 0 :(得分:1)
这个问题包含一个问题。嵌套服务不应该被测试。单元测试是关于测试一个单元,一次一个。一项服务(ipmaService
)经过测试,其他服务被模拟。
此列表
beforeEach(angular.mock.module(serviceModule));
beforeEach(angular.mock.module(LocalStorageModule));
beforeEach(angular.mock.module(constantsModule));
应该成为
var localStorageServiceMock = { get: jasmine.createSpy().and.returnValue(...) };
beforeEach(angular.mock.module(serviceModule, {
localStorageService: localStorageServiceMock,
appConfig: ...,
locationStorageKey: ...
}));
幸运的是,我们有一个单独的类导出,带有ES6模块和default
:
import serviceModule, { IPMAService } from './IPMAService.service';
这使我们有机会在使用inject
实例化服务之前在类原型方法上设置间谍:
beforeEach(() => {
spyOn(IPMAService.prototype, '_getLocationsFromService').and.callThrough();
});
...
expect(service._getLocationsFromService).toHaveBeenCalled();
或者,可以在某些服务规范中模拟该方法,以提高粒度并专注于测试方法。
在构造函数中监视服务自己的方法并不是一件大事,但它增加了规范的强度。