2017-02-21 9 views
9

私は別のサービス(InteractWithServerService)に依存するサービス(ChildService)を持っています。後のサービス(InteractWithServerService)は、サーバー呼び出しを行い、 "any"型の観測可能なものを返すために使用されます。簡単にするために、それが観測可能に戻ると仮定してください。 ChildServiceの単体テストを作成しようとしています。私は依存サービスを模擬する際ユニットテストspyOn observable service in angular2

ChildService

@Injectable() 
export class ApplicationService { 
    constructor(private interactWithServerService:InteractWithServerService){;} 

    public GetMeData():string { 
     var output:string;  
     this.interactWithServerService.get("api/getSomeData"). 
      subscribe(response =>{console.log("server response:", response); 
      output=response});   
     return output; 
    } 
} 

ServerInteractionService

@Injectable() 
export class InteractWithServerService {   
    constructor(private http: Http) { 
     ; 
    }  
    get(url: string): Observable<any> {   
     return this.http.get(this.url); 
    }  
} 

テストケースが正常に動作します。すなわち、

class MockInteractWithServerService { 
    get() { 
     return Observable.of("some text"); 
    }   
} 

describe('Service:ChildService',() => { 
    let childService: ChildService; 

    beforeEach(() => { 
     TestBed.configureTestingModule({ 
      providers: [ 
      { provide: InteractWithServerService, useClass: MockInteractWithServerService }, 
       ChildService], 
     }); 


    beforeEach(inject([ChildService], (actualService: ChildService) => { 
     childService= actualService;   
    })); 

    fit('should call server-call testCall()',() => { 
     let actualReturnvalue= childService.GetMeData();   
     expect(actualReturnvalue).toBe("some text"); 
    }); 
}); 

上記の方法は「n」依存関係の「n」モッククラスを作成する可能性があるため、推奨されていません。だから私はspyOnを使って単体テストを作りたいと思っています。 しかし、テストケースは機能せず、 "エラー:HTTPのプロバイダがありません!"というエラーメッセージがスローされます。私はエラーが何であるか理解していますが、なぜ私は依存サービスを監視していますが、なぜそれがスローされるのかを知りたいと思います。 "spyOn"が動作していないように見えます。

describe('Service:ChildService',() => { 
    let childService: ChildService; 

    beforeEach(() => { 
     TestBed.configureTestingModule({ 
      providers: [ 
      InteractWithServerService, 
       ChildService], 
     }); 

     spyOn(InteractWithServerService.prototype, 'get').and 
      .callFake(()=>  
      {return Observable.of("some text");});  
    }); 
    beforeEach(inject([ChildService], (actualService: ChildService) => { 
     childService= actualService;   
    })); 

    fit('should call server-call testCall()',() => { 
     let actualReturnvalue= childService.GetMeData();   
     expect(actualReturnvalue).toBe("some text"); 
    }); 
}); 

明らかなものがありませんか?

答えて

8

However, the test case doesn't work and throws "Error: No provider for Http!".

角度は、あなたがモッククラスを作成するのではなく、何ができるか、まだ

providers: [ 
InteractWithServerService, 
    ChildService], 

それを作成しようとしているので、あなたはまだ、providersでサービスを持っているためのような何かをちょうど行うことです

providers: [ 
    { 
    provide: InteractWithServerService, 
    useValue: { get: Observable.of(..) } 
    } 
] 

ここでは、任意のオブジェクトを提供するuseValueを使用しています。それは注入時に使用される値になります。上のケースでは、あなたのモックメソッドを使った任意のオブジェクトです。

あなたが異なる値を提供できるようにスパイしたい場合は、InteractWithServerServiceを注入でき、その後、あなたができる

spyOn(service, 'get').and.returnValue(Observable.of(...)) 
// do test 

を行うもう一つは、ダミーのオブジェクト

{ provide: Http, useValue: {} } 
とのHttpモックです

InteractWithServerServiceが機能します(現在のようにプロバイダクラスにクラスを追加するだけです)。そして、あなたはそれをスパイすることができます

let service = TestBed.get(InteractWithServerService); 
spyOn(service, 'get').and.returnValue(..) 
// do test 
+0

ありがとう@peeskillet。魅力のように動作します。関心のあることは、 "useValue"だけで、呼び出すメソッドごとに任意のオブジェクトを返すことです。間違いなく汚れているように見えます。これは、角度を使ってテストを書くのですか? –

+0

「任意のオブジェクト」はモッククラスを使用することとまったく同じではありません。違いは、クラス内にカプセル化されている点だけです。結局、それらはどちらもただのオブジェクトです。あなたのクラスは、実際のサービスインターフェイスを拡張しません。それが何を恣意的にしないのでしょうか重要なことは、オブジェクトには呼び出されるメソッドがあることだけです。 –

+0

私は、モッククラスがuseValueよりも優れていると主張していません。私の主張は、モッククラスとuseValueソリューションは、従属クラスを注入してスパイするという古い方法と比べるときれいに見えません。 –