2016-04-05 11 views
1

私はangular2アプリケーションをテストしようとしています。私は、バックエンドにデータを送信するために、観察を使用してログインフォームを、持っている:ジャスミン:イベントでオブザーバブルをテストする

私が観察返すサービス機能、上のスパイを追加していた試験で
doLogin() { 
    this.usersService.login(this.model) 
     .subscribe((data) => { 
      console.log("In observable: " + data.isSuccess); 
      if (!data.isSuccess) { 
       this.alerts.push({}); 
      } 
     }); 
} 

、そのコンポーネントは、その上で動作することができるように:

すべての準備が整ったとき
usersService.login.and.returnValue(Observable.of(
    <LoginResponse>{ 
     isSuccess: true 
    })); 

は、私はコンポーネントで機能をdoLoginトリガ送信ボタン、上のイベントをディスパッチ:

submitButton.dispatchEvent(new Event("click")); 
fixture.detectChanges(); 

それが正常に動作します。 usersService.loginは、テストで呼び出されている場合、私がチェックしたときに残念なことに、:

expect(usersService.login).toHaveBeenCalled(); 

、観察が終了しませんでした、ログインがまだ呼び出されていないので、私は、エラーを取得します。

観察可能な状態になった後、スパイを確認するにはどうすればよいですか?

答えて

1

コンポーネントにサービスをどのように設定するのか分かりませんが、TestComponentBuilderから作成されたコンポーネントのプロバイダを上書きすると、私のために機能します。

サンプルを取ってみましょう。私はをクリックしたとき、私はそれをテストしたい

@Component({ 
    selector: 'my-list', 
    providers: [MyService], 
    template: ` 
    <ul><li *ngFor="#item of items">{{ item }}</li></ul> 
    <div id="test" (click)="test()">Test</div> 
    ` 
}) 
export class MyList implements OnInit { 
    items:Array<string>; 
    service:MyService; 

    constructor(private service:MyService) { 
    } 

    test() { 
    this.service.getDogs().subscribe(
     (dogs) => { 
     this.items = dogs; 
     }); 
    } 
} 

import {Observable} from 'rxjs/Rx'; 

export class MyService { 
    getDogs() { 
    return Observable.of([ 's1', 's2', ... ]); 
    } 
} 

コンポーネントがボタンをクリックすると、非同期のリストを表示するには、このサービスを使用しています。私は、文字列のリストを返すサービスを持っています"Test"ボタンを押すと、コンポーネントのメソッドtestが呼び出され、サービスのメソッドが間接的に呼び出されます。

このため、サービスを直接インスタンス化し、TestComponentBuilderを使用してコンポーネントをロードするテストを作成します。この場合、createAsyncを呼び出す前にoverrideProvidersメソッドを呼び出す必要があります。こうすることで、あなたのスパイドサービスを提供して通話の通知を受けることができます。ここではサンプルです:

let service:MyService = new MyService(); 

beforeEach(() => { 
    spyOn(service, 'getDogs').and.returnValue(Observable.of(
     ['dog1', 'dog2', 'dog3'])); 

}); 

it('should test get dogs', injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => { 
    return tcb.overrideProviders(MyList, [provide(MyService, { useValue: service })]) 
       .createAsync(MyList).then((componentFixture: ComponentFixture) => { 
     const element = componentFixture.nativeElement; 
     componentFixture.detectChanges(); 

     var clickButton = document.getElementById('test'); 
     clickButton.dispatchEvent(new Event("click")); 

     expect(service.getDogs).toHaveBeenCalled(); 
    }); 
})); 

編集

イベントが非同期的にトリガされますので、あなたがfakeAsyncを使用することを検討することができます。後者は、非同期処理が処理されるときを完全に制御し、非同期処理を同期処理に変換することを可能にします。

あなたが詳細については、あなたがこの質問を見ている可能性が

fakeAsync((): void => { 
    var clickButton = document.getElementById('test'); 
    clickButton.dispatchEvent(new Event("click")); 

    expect(service.getDogs).toHaveBeenCalled(); 
}); 

にあなたのテストの処理をラップすることができます:

+0

おかげで、あなたが答えるために。私は同じ方法でそれを行いますが、私の場合、サービスメソッドがコンポーネントによって呼び出される前にtoHaveBeenCalledがチェックされています。 –

+0

私は分かりません;-)コンポーネントはサービスを同期的に呼び出し、サービスメソッドは何かを非同期で実行し、observableを返します。右? –

+0

はい、そうですが、私が理解しているように、dispatchEventは非同期なので、test()関数は非同期モードで呼び出され、getDogsが呼び出される前にexpectがチェックされる可能性があります。 –

関連する問題