2016-10-21 1 views
1

Ich versuche Unit-Test einen Angular-Dienst zu testen, der einen anderen Dienst injiziert, der $ injector verwendet, anstatt die Dienstabhängigkeit als Argument zu übergeben. Der eingefügte Dienst ist dynamisch - er könnte einer von mehreren verschiedenen Diensten sein - und kann daher nicht als Funktionsargument übergeben werden.

Der zu testende Dienst ermittelt, ob die Anwendung online oder offline ist, verwendet dann das Strategiemuster, um entweder einen HTTP-Aufruf (wir sind online, also die Strategie ist "remote") oder lokalen Speicher zu verwenden Daten (wir sind offline, also ist die Strategie "lokal"). Es wird in einer Reihe von Szenarien in der gesamten Anwendung verwendet, sodass der Dienst und die Servicemethode, die anschließend aufgerufen werden, dynamisch sind. Einfacher, die vereinfachten, relevant, Code zu erhalten:

class NetworkStrategyService { 
    constructor (private Offline, private $injector) {} 

    fulfill (config) { 
     this.Offline.check() 
      .then(
       () => { 
        // we're online 
        const service = $injector.get(config.remote.service); 
        service[config.remote.method](config.remote.data) 
         .then(() => { 
          // Do something with the data 
         }) 
       }, 
       () => { 
        // Grab it from local storage 
       } 
      ) 
    } 

} 

Mein Problem ist, weil ich den Dienst nicht in gewohnter Weise in meinen Unit-Tests injizieren kann, ich weiß nicht, wie Sie diesen Code zu testen. Ich habe die Config verspottet, jetzt will ich testen, ob die richtigen Service-Methoden aufgerufen werden, während online und offline, wie zum Beispiel:

it (`calls the remote service, with the remote method, if we're online`,() => { 
    const remoteMethod = spyOn(config.remote.service, config.remote.method); 
    // Set up, to get a successful Offline.check() outcome 
    expect(remoteMethod).toHaveBeenCalledWith(config.remote.data); 
}); 

Wie kann ich sicherstellen, dass der verspottete Service ist ein Dienst, und übergeben Sie es in meinen Dienst im Test?

Antwort

0

OK, scheine ich es gelöst haben:

let deferred; 
let config = { 
    remote: { 
     service: 'RemoteService', 
     method: 'remoteAction', 
     data: {alpha:1} 
    }, 
    local: ... 
}; 

beforeEach(() => { 
    angular.mock.module(($provide) => { 
     $provide.service(config.remote.service,() => { 
      return { 
       [config.remote.method]:() => {} 
      }; 
     }); 
    }); 
}); 

beforeEach(() => { 
    inject((_$q_, _$rootScope_, _$injector_) => { 
     $q = _$q_; 
     $scope = _$rootScope_.$new(); 
     $injector = _$injector_ 
    }); 
    deferred = $q.defer(); 
}); 

beforeEach(() => serviceUnderTest = new NetworkStrategyService(Offline, $injector)); 

it (`calls the remote service, with the remote method, if we're online`,() => { 
    let dynamicService; 
    inject((_RemoteService_) => { 
     dynamicService = _RemoteService_; 
    }); 
    serviceUnderTest.strategy = 'remote'; 
    const dynamicMethod = spyOn(dynamicService, config.remote.method).and.returnValue(deferred.promise); 
    serviceUnderTest.makeCall(config); 
    deferred.resolve(); 
    $scope.$apply(); 
    expect(dynamicMethod).toHaveBeenCalledWith(config.remote.data); 
}); 
Verwandte Themen