web-dev-qa-db-ja.com

angle2でのspyOn監視可能サービスの単体テスト

別のサービス(InteractWithServerService)に依存するサービス(ChildService)があります。後者のサービス(InteractWithServerService)は、サーバー呼び出しを行い、「任意の」タイプのオブザーバブルを返すために使用されます。簡単にするために、observableを返すと仮定しましょう。 ChildServiceの単体テストを作成しようとしています。

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

明らかな何かが欠けていますか?

12
Sudhir V

ただし、テストケースは機能せず、「エラー:Httpのプロバイダーがありません!」がスローされます。

まだprovidersにサービスがあるため、Angularはまだ作成しようとしています

providers: [
 InteractWithServerService,
    ChildService],

モックを作成する代わりにできることclassは、

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

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

異なる値を提供できるようにスパイしたい場合は、InteractWithServerServiceを挿入してから

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

もう1つできることは、ダミーオブジェクトでHttpをモックすることです。

{ provide: Http, useValue: {} }

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

let service = TestBed.get(InteractWithServerService);
spyOn(service, 'get').and.returnValue(..)
// do test
19
Paul Samsotha

ジャスミング2.6.2の使用:getは関数なので、上記の答えに矢印関数表記を追加する必要があります。

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