3

私は 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 が含まれています。そうでなければ、asyncanddetectChangesアプローチは必要ありませんでした。

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 が解決されないため、アサーション コードが実行されず、テストが同じタイムアウトで失敗することです。

したがって、破棄の提案は特定の単純化されたテストで機能しますが、実際のテストを修正することはできません。

ありがとう

ベン

4

1 に答える 1