2017-03-20 20 views
4

私はangle2アプリケーションを作成していますが、ジャスミンを使って非同期コードのテストを書く方法を理解できません。どんな理由であれ、私の状況にはあまりにも多くの例が見えることはありません。ジャスミンを使ったAngular2非同期ユニットテスト

私は現在、別のサービスに非同期依存性を持つサービス(コンポーネントではありません)をテストしようとしています。私は、非同期呼び出しの結果をチェックするのに有効なテストのどの時点で100%確実ではない。サービスの非同期ハンドラの内部でexpect()に電話するだけですか?

service.foo() 
    .then((data) => { 
     //do I check the results in here? 
     expect(data).toEqual({ a: 1, b: 2 }); 
     expect(mockDep.get).toHaveBeenCalled(); 
    }); 

これは完全なテストです。

import { TestBed, inject } from '@angular/core/testing'; 
import { MyService } from './my.service.ts'; 
import { MyDependency } from './dependency.service.ts'; 

class MockDependency { 
    doSomething(): Promise<any> { 
     throw Error('not implemented'); 
    }; 
} 

describe('some tests',() => { 
    beforeEach(() => { 
     TestBed.configureTestingModule({ 
      providers: [ 
       MyService, 
       { 
        provide: MyDependency, useClass: MockDependency 
       } 
      ] 
     }); 
    }); 
}); 

it('should do something', inject([MyService, MyDependency], (service: MyService, mockDep: MyDependency) => { 
    spyOn(mockDep, 'doSomething').and.callFake(function() { 
     return Promise.resolve({ a: 1, b: 2 }); 
    }); 

    service.foo() 
     .then((data) => { 
      //do I check the results in here? 
      expect(data).toEqual({ a: 1, b: 2 }); 
      expect(mockDep.get).toHaveBeenCalled(); 
     }); 
})); 
+0

はい、通常は 'expect'を' then'に入れます。非同期テストでは、 'async'または' fakeAsync'で 'inject'をラップする必要があります。 – estus

答えて

13

テストが実際に信頼できるものかどうかを確認するには、非同期テストを扱う2つの側面があります。

まず、結果を非同期に取得する場合は、テストする前に結果が利用可能になるまで待つ必要があります。

したがって、非同期の結果が約束の場合は、質問に記載されているように、ハンドブックにexpectを入れることができます。

自分自身が気にしなければならない第2の問題は、テスト自体が肯定的(または否定的)の結果を出す前にあなたの期待を待つように強制することです。これに対処しなければ、期待通りの結果が得られない場合がありますが、非同期アクションが完了するまでテストが完了するのを待っていないため、テストは偽陽性を報告します。

「テスト待ち」にはいくつかの方法があります。

純粋なジャスミンの方法は、完了したハンドラを関数に渡すことです。ジャスミンは、テストが完了したことを考慮する前に、完了したハンドラが呼び出されるまで待機します。

例えば、

it('tests an async action', (done) => { 
    asyncAction().then(result => { 
    expect(result).toEqual(true); 
    done(); 
    }); 
}); 

ただし、angleのテストフレームワークには2つのオプションが追加されています。最初は、非同期プログラミングに慣れていれば把握が容易です。

it('tests an async action', async(() => { 
    asyncAction().then(result => { 
    expect(result).toEqual(true); 
    }); 
})); 

この場合、基本的にはテストハンドラを非同期関数でラップします。この関数は、テストが完了する前に、非同期の結果(例えば、約束、観測可能なものなど)が結果を返すのをテストが待つように強制します。

fakeAsyncを使用すると、テストの非同期性を完全に隠すことができます。

it('tests an async action', fakeAsync(() => { 
    let myResult; 
    asyncAction().then(result => { 
    myResult = result; 
    }); 

    tick(); <--- force all async actions to complete 
    expect(myResult).toEqual(true); 
})); 

fakeAsyncはすべての非同期関数にフックし、それらを同期として扱うことができます。 tick()関数を使用して、非同期タスクが完了する前に「テストを待機させる」ことができます。
(それはそれほどありませんが、概念的には、そういう意味で考えることができます)。

See the Angular docs to learn more

+0

良い答え。1つの質問:async()を使用する例では、ジャスミンのdone()関数を呼び出すことができません。それは必要ですか? – d512

+0

@ d512、そうです。asyncを使用している場合、done()呼び出しは不要です。私はその答えを反映するためにコードを更新しました – snorkpete

関連する問題