2016-08-02 11 views
1

私は、午後過ごして、期待どおりに機能しているサービスの単体テストを成功させようとしました。単体テストを渡す別のサービス(依存関係はありません)があるため、問題は注入された依存関係から発生します。Angular JSネストされたサービスユニットテスト

サービスがこの

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;

である私は、ユニットテストについて多くを読んで、私はそれが仕事を得るように見えることはできません。

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

:これは(: "例外TypeError:objectに未定義またはnull変換できません" それは、噴射機能にクラッシュすることを与えられていなくても、基本的な.toBeDefined()、)私の最後の試みでしたまた、私はこの基本的なテストをパスした後、getLocationsメソッドをテストするにはどうすればよいか知りたいです。_getLocationsFromServiceメソッドとローカルストアジャスミンのスパイオンを使用する必要がありますが、少しの助けを借りてuldはすばらしいです)。

ありがとうございます。

EDIT

これが受け入れ答えといくつかのより多くの研究を混合、私の最終的な解決策でした。将来的にユニットテストについて絶望的な人に役立つことを願っています。

:私は質問がキャッチが含まれているサービス

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

 

 
});

答えて

1

からlocationStorageKey依存性を取り除きます。ネストされたサービスはテストしないでください。単体テストは、一度に1つずつ、単体テストをテストすることです。 1つのサービス(ipmaService)がテストされ、他のサービスがモックされます。これは私たちに機会を与える

import serviceModule, { IPMAService } from './IPMAService.service'; 

このリスト

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

になるべき、我々はdefaultと一緒にES6モジュールを搭載した別のクラスのエクスポートを持っていますサービスが瞬時になる前にクラスのプロトタイプメソッドにスパイを設定するinjectとiatedは:

beforeEach(() => { 
spyOn(IPMAService.prototype, '_getLocationsFromService').and.callThrough(); 
}); 
... 
expect(service._getLocationsFromService).toHaveBeenCalled(); 

あるいは、この方法は、粒状性を改善し、試験方法を集中するために、いくつかのサービス仕様にモックすることができます。

コンストラクターでサービス独自のメソッドをスパイすることは大きな問題ではありませんが、スペックに強みが加わります。

+0

午前中に試してみてください。返信いただきありがとうございます! – Bernardo

+0

私は、私が見た他の人とあなたの答えを混ぜ合わせてしまいました。ありがとうございました。 – Bernardo

+0

@Bernardoよろしくお願いします。 – estus

関連する問題