2016-08-02 14 views
1

Ich verbrachte den ganzen Nachmittag damit, einen Komponententest für einen Dienst zu schreiben, der wie erwartet funktioniert, ohne Erfolg. Das Problem rührt von den eingefügten Abhängigkeiten her, weil ich einen anderen Dienst habe, der die Komponententests besteht (er hat keine Abhängigkeiten).Angular JS Nested Services Unit Test

Der Service ist dieses

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;

ich viel über Unit-Tests gelesen, und ich kann nicht scheinen, damit es funktioniert. Das war mein letzter Versuch (nicht einmal eine grundlegende .toBeDefined(), da es in der Funktion inject stürzt ab: "Typeerror: Kann nicht konvertieren undefined oder null, um das Objekt"):

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

auch ... nachdem ich diesen grundlegenden Test bekommen passieren/Arbeit, würde ich gerne wissen, wie kann ich zum Beispiel prüft die getLocations Methode, da sie auf der _getLocationsFromService Methode und hängen local (ich glaube, ich Ich muss Jasmins SpyOn benutzen, aber ein wenig Hilfe old sei großartig).

Vielen Dank im Voraus.

EDIT

Dies war meine letzte Lösung, die die akzeptierte Antwort und etwas mehr Forschung zu mischen. Hoffe es hilft jemandem in der Zukunft, der verzweifelt über Unit Tests ist.

HINWEIS: Ich entfernte die locationStorageKey Abhängigkeit vom Dienst

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

 

 
});

Antwort

1

Die Frage einen Haken enthält. Geschachtelte Dienste sollten nicht getestet werden. Beim Komponententest geht es darum, eine Einheit einzeln zu testen. Ein Dienst (ipmaService) wird getestet, die anderen werden verspottet.

Diese Liste

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

Zum Glück werden sollte, haben wir eine eigene Klasse Export mit ES6 Module neben mit default:

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

Dies gibt uns die Möglichkeit zu Richten Sie Spione auf Klassen-Prototyp-Methoden ein, bevor der Dienst sofort ausgeführt wird iated mit inject:

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

Alternativ kann das Verfahren in einigen Dienstleistungsdaten spottet Körnigkeit zu verbessern und bewährte Methoden zu konzentrieren.

Ausspionieren der eigenen Methode im Konstruktor ist keine große Sache, aber es fügt die Stärke zu Spezifikationen hinzu.

+0

Ich werde es als erstes am Morgen versuchen, danke für die schnelle Antwort! – Bernardo

+0

Ich habe deine Antwort mit einigen anderen gemischt, die ich gesehen habe, und ich habe meinen Beitrag mit meiner Lösung bearbeitet. Danke für die Hilfe :) – Bernardo

+0

@Bernardo Gern geschehen. – estus