私は Angular2.0.1 を使用しており、いくつかの非同期タスクを使用して角度コンポーネントの周りに単体テストを作成しようとしていました。かなり一般的なことだと思います。彼らの最新のテスト例にも、この種の非同期テストが含まれています (こちらを参照)。
ただし、私自身のテストは決して成功せず、常にメッセージで失敗します
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
簡単に言えば、問題の実際の原因を特定するのに何時間もかかりました。私はライブラリ angular2-moment を使用しており、そこで amTimeAgo というパイプを使用していました。このパイプには、決して削除されない window.setTimeout(...) が含まれています。amTimeAgo パイプを削除した場合、テストは成功しますが、それ以外の場合は失敗します。
問題を再現するための非常に基本的なコードを次に示します。
testcomponent.html:
{{someDate | amTimeAgo}}
testcomponent.ts:
import { Component } from "@angular/core";
import * as moment from "moment";
@Component({
moduleId: module.id,
templateUrl: "testcomponent.html",
providers: [],
})
export class TestComponent{
someDate = moment();
constructor() {
}
}
testmodule.ts
import { NgModule } from "@angular/core";
import {MomentModule} from 'angular2-moment';
import { TestComponent } from './testcomponent';
@NgModule({
imports: [
MomentModule,
],
declarations: [
TestComponent,
]
})
export class TestModule {
}
testcomponent.spec.ts:
import { async, TestBed, ComponentFixture } from "@angular/core/testing";
import { TestComponent } from './testcomponent';
import { TestModule } from './testmodule';
let component: TestComponent;
let fixture: ComponentFixture<TestComponent>;
function createComponent() {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
fixture.detectChanges();
return Promise.resolve();
}
describe("TestComponent", () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
TestModule],
}).compileComponents();
}));
it('should load the TestComponent', async(() => {
createComponent().then(() => {
expect(component).not.toBe(null);
});
}));
});
これをうまくテストする方法を知っている人はいますか? afterEach で「残りの」タイムアウトをすべて強制終了することはできますか? または、非同期コードが実行されているゾーンをリセットして、この問題を解決できますか?
他の誰かがこれに遭遇したか、これをうまくテストする方法を知っていますか? ヒントをいただければ幸いです。
更新:
@peeskillet が を使用した解決策を示唆した後fixture.destroy()
、実際のテストでこれを試してみました (ここの例は、問題を再現するために必要な最小限のコードです)。実際のテストにはネストされた promise が含まれています。そうでなければ、async
anddetectChanges
アプローチは必要ありませんでした。
destroy の提案は素晴らしく、単純なテストの問題を解決するのに役立ちますが、実際のテストには、ネストされた promise が適切に解決されていることを確認する次のステートメントが含まれています。
it('should check values after nested promises resolved', async(() => {
createComponent().then(() => {
fixture.whenStable().then(() => {
component.selectedToolAssemblyId = "2ABC100035";
expect(component.selectedToolAssembly).toBeDefined();
expect(component.selectedToolAssembly.id).toBe("2ABC100035");
fixture.destroy();
});
fixture.detectChanges();
});
}));
問題は、ページ内の amTimeAgo パイプを使用すると、fixture.whenStable()
promise が解決されないため、アサーション コードが実行されず、テストが同じタイムアウトで失敗することです。
したがって、破棄の提案は特定の単純化されたテストで機能しますが、実際のテストを修正することはできません。
ありがとう
ベン