2017-05-08 9 views
2

私はこれをテストする可能性がどのように思っていた以下の機能

injectService(serviceToInject: string, methodToInvoke: string){ 
    let service = this.$injector.get(serviceToInject); 
    service[methodToInvoke](); 
} 

を持つつのサービスがありますか?私はこれを試しました:

(function() { 
'use strict'; 

describe.only('ServiceA tests', function() { 
    let ServiceA; 

    beforeEach(angular.mock.module('main')); 

    beforeEach(inject(function (_ ServiceA_, _$injector_) { 
     ServiceA = _ServiceA_; 
     $injector = _$injector_; 
    })); 

    describe.only('injectServiceAndInvoke', function() { 
     it('given a string serviceToInject which is a valid service name and a string methodToInvoke which is valid method name without parameters, it should inject the service and call the method',() => { 

      let serviceName = 'validServiceName'; 
      let methodWithoutParams = 'method'; 
      let injectedService = $injector.get(serviceName); 
      // sandboxSinon.stub(ButtonService.$injector, 'get').withArgs(serviceName).returns(stubbedService); 

      let methodToBeCalled = sandboxSinon.stub(injectedService, methodWithoutParams).withArgs(undefined); 


      sandboxSinon.stub(ServiceA, 'tokenizeState').withArgs(methodWithoutParams).returns([methodWithoutParams, undefined]); 
      ServiceA.injectServiceAndInvoke(serviceName, methodWithoutParams); 
      expect(methodToBeCalled.calledOnce).to.equal(true); 
     }); 

    }); 

}); 

})(); 

私は正しくサービス 'validServiceName'が存在しないというエラーが発生しました。私も$ injector.getをスタブしようとしましたが、このスタブを返すものと、このサービスからメソッドを呼び出す方法を理解していません。

+0

してください、テストからより多くのコードを提供し、その答えは、アカウントにそれを取ることができます。 – estus

+0

テストで更新しました – geo

+0

これは、サービスロケータと非常によく似ています。なぜあなたはこれを行う必要があり、実装をテストしているのか、フレームワークをテストしていますか? –

答えて

3

$injectorサービスがグローバルに使用されているため、DIを介して完全にモックできません。これは本当に分離された単体テストの障害です。しかし、本当に悪いことで単一条件の模擬テストは脆弱なことはありませんので、:

const injectedService = { methodName: sinon.stub() }; 
sinon.stub($injector, 'get'); 
$injector.get.withArgs('injectedServiceName').returns(injectedService) 
$injector.get.callThrough(); 
ServiceA.injectServiceAndInvoke('injectedServiceName', 'methodName'); 

expect($injector.get.withArgs('injectedServiceName').calledOnce).to.equal(true); 
expect(injectedService.methodName.calledOnce).to.equal(true); 
expect(injectedService.methodName.calledWith()).to.equal(true); 

しかし、サービスはプロパティとして$injectorを持っているので、プロパティは後に嘲笑することができますので、これはテストのための良いオプションを提供サービスの代わりに本物の$injector.getをあざけるのインスタンス化:

const injectedService = { methodName: sinon.stub() }; 
const injectorMock = { get: sinon.stub() }; 
injectorMock.get.withArgs('injectedServiceName').returns(injectedService); 
ServiceA.$injector = injectorMock; 
ServiceA.injectServiceAndInvoke('injectedServiceName', 'methodName'); 

expect(injectorMock.get.withArgs('injectedServiceName').calledOnce).to.equal(true); 
expect(injectedService.methodName.calledOnce).to.equal(true); 
expect(injectedService.methodName.calledWith()).to.equal(true); 
+0

非常に良い説明。ありがとうございます – geo

+0

ようこそ。 – estus

関連する問題