Angular 2の単体テスト用にモックバックエンドから結果を取得しようとしています。現在、タイムアウトのfakeAsync
を使用して、時間の経過をシミュレートしています。
現在の作業単位テスト
_it('timeout (fakeAsync/tick)', fakeAsync(() => {
counter.getTimeout();
tick(3000); //manually specify the waiting time
}));
_
ただし、これは、手動で定義されたタイムアウトに制限されることを意味します。非同期タスクが完了したときではありません。私がやろうとしているのは、テストを続行する前に、タスクが完了するまでtick()
を待機させることです。
これは意図したとおりに機能しないようです。
fakeAsync
とtick
の答え ここ を読んで説明します:
tick()は非同期の時間経過をシミュレートします。
このシナリオをシミュレートする plnkrの例 を設定しました。
ここでは、タイムアウトを持つ内部非同期タスクを呼び出すgetTimeout()
メソッドを呼び出します。テストでは、tick()
メソッドを呼び出した後、ラップしてgetTimeout()
を呼び出します。
counter.ts
_getTimeout() {
setTimeout(() => {
console.log('timeout')
},3000)
}
_
counter.specs.ts
_it('timeout (fakeAsync/tick)', fakeAsync(() => {
counter.getTimeout();
tick();
}));
_
ただし、ユニットテストは「エラー:1個のタイマーがまだキューに残っています」というエラーで失敗します。
angular repo の問題は、これと何か関係がありますか?
この方法でtick()
を使用してタイムアウト関数を待つことは可能ですか?または、私が使用できる別のアプローチはありますか?
fakeAsync
の目的は、仕様内で時間を制御することです。 tick
は時間の経過をシミュレートするために使用される同期関数であるため、時間を待機しません。非同期関数が完了するまで待機する場合は、async
およびwhenStable
を使用する必要がありますが、この例では、仕様の合格に3秒かかるため、これはお勧めしません。
counter.spec.tsが失敗する理由は、0秒の経過のみをシミュレートしたためです(通常はイベントループの次のティックを表すために使用されます)。そのため、仕様が完了すると、まだモックされたタイマーがアクティブになり、仕様全体が失敗します。タイムアウトがモックされ、処理されていないことを通知することで、実際に適切に動作しています。
基本的に、あなたはfakeAsync
とtick
を使用するつもりのない方法で使用しようとしていると思います。提案した方法でタイムアウトをテストする必要がある場合、最も簡単な方法はsetTimeout
関数をモックして、使用する時間に関係なくメソッドを呼び出すことです。
[〜#〜] edited [〜#〜]タイマーをクリアしたいという関連問題に遭遇しました。これはテスト中の部分ではなかったので、どのくらい長く気にしませんでした取った。私は試した:
tick(Infinity);
これは機能しましたが、非常にハッキーでした。私はで行きました
discardPeriodicTasks();
そして、私のタイマーはすべてクリアされました。
各テストの最後に次を追加します。
fixture.destroy();
flush();
これを試して:
// I had to do this:
it('timeout (fakeAsync/tick)', (done) => {
fixture.whenStable().then(() => {
counter.getTimeout();
tick();
done();
});
});
非同期
test.service.ts
export class TestService {
getTimeout() {
setTimeout(() => { console.log("test") }, 3000);
}
}
test.service.spec.ts
import { TestBed, async } from '@angular/core/testing';
describe("TestService", () => {
let service: TestService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [TestService],
});
});
it("timeout test", async(() => {
service.getTimeout();
});
});
偽の非同期
test.service.ts
export class TestService {
readonly WAIT_TIME = 3000;
getTimeout() {
setTimeout(() => { console.log("test") }, this.WAIT_TIME);
}
}
test.service.spec.ts
import { TestBed, fakeAsync } from '@angular/core/testing';
describe("TestService", () => {
let service: TestService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [TestService],
});
});
it("timeout test", fakeAsync(() => {
service.getTimeout();
tick(service.WAIT_TIME + 10);
});
});
私は通常、サービスで使用するユニットテストでflushMicrotasksメソッドを使用します。 tick()はflushMicrotasksに非常に似ているが、jasmine tick()メソッドも呼び出すことを読みました。