jasmine:非同期コールバックは、jasmine.DEFAULT_TIMEOUT_INTERVALで指定されたタイムアウト時間内に呼び出されませんでした


140

私はという角度のサービスを持っていますrequestNotificationChannel

app.factory("requestNotificationChannel", function($rootScope) {

    var _DELETE_MESSAGE_ = "_DELETE_MESSAGE_";

    function deleteMessage(id, index) {
        $rootScope.$broadcast(_DELETE_MESSAGE_, { id: id, index: index });
    };

    return {
       deleteMessage: deleteMessage
    };

});

私はジャスミンを使用してこのサービスを単体テストしようとしています:

"use strict";

describe("Request Notification Channel", function() {
    var requestNotificationChannel, rootScope, scope;

    beforeEach(function(_requestNotificationChannel_) {
        module("messageAppModule");

        inject(function($injector, _requestNotificationChannel_) {
            rootScope = $injector.get("$rootScope");
            scope = rootScope.$new();
            requestNotificationChannel = _requestNotificationChannel_;
        })

        spyOn(rootScope, '$broadcast');
    });


    it("should broadcast delete message notification", function(done) {

        requestNotificationChannel.deleteMessage(1, 4);
        expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4 });
        done();       
    });
});

私はJasmineの非同期サポートについて読みましたが、JavaScriptを使用した単体テストはかなり新しいので、JavaScriptを機能させることができませんでした。

エラーが発生しました:

Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL

テストの実行に時間がかかりすぎる(約5秒)。

誰かが私のコードの実際の例を説明するのを手伝ってくれる?


1
イベントの処理は通常、ダイジェストサイクルで行われます。Jasmineの非同期テストパターンを使用する代わりに、scope。$ apply()をテストに追加してみてください
Eitan Peer

これは機能しません。scope。$ apply();を追加しました。requestNotificationChannel.deleteMessage(1、4)を呼び出した直後に同じエラーが発生する...
Mdb

非同期テストの実行に時間がかかる場合にも同じエラーが発生しますJest予想 -デバッグ中や変数の検査に時間が非常に一般的です。
Dan Dascalescu 2017年

代わりに、より小さいタイムアウトを使用してみてください。timeout = 5000を使用しているときにこのエラーが発生しました。2000に置き換えたところ、うまくいきました。
マリーナリアズ

1
私の靴の誰かを助けるためにここにこれを残します。Dockerコンテナー内でテストを実行しているときにこのエラーが発生しました。テストは問題なく成功することもありますが、失敗することもあります。なんらかの競合状態だと思ったのですが、その理由がわかりませんでした。afterEachデータベースをクリアするステップがあることに気づきました(deleteManyメソッド)。メソッドに追加することjest.setTimeout(30000);beforeAllこれが修正されたようです-データベースの削除は(条件内の)ネットワーク呼び出しであるため、3秒より長くかかってスローされていたためと思います。
nkhil

回答:


231

it関数(done以下のコード)に引数があると、Jasmineは非同期呼び出しを試みます。

//this block signature will trigger async behavior.
it("should work", function(done){
  //...
});

//this block signature will run synchronously
it("should work", function(){
  //...
});

done引数の名前には違いがありません。その存在が重要です。コピー/パスタが多すぎるため、この問題に遭遇しました。

ジャスミン Asynchronous Supportのドキュメントでは、引数(done上記の名前)は、非同期関数が完了したときにJasmineに通知するために呼び出すことができるコールバックであることに注意しています。これを呼び出さない場合、Jasmineはテストが完了したことを認識せず、最終的にタイムアウトします。


3
describeのargsにも同じことが言えます(angularでは、injectを呼び出してそれを行う必要があります)
Narretz

@MartinBlissドキュメント化されています。ドキュメントを参照するために編集を提案しました:stackoverflow.com/suggested-edits/2434606
Vincent

39
将来この質問に遭遇するランダムなGoogle社員に注意してください。分度器を使用していてこの問題に遭遇した場合、この答えはあなたが探しているものではありません-分度器がコールバックを単独で呼び出します。
Vincent、

それは私の問題を修正し、それは同じcuplrit "copy / pasta"によって引き起こされました
shaikh

1
@Vincentこのエラーが発生した場合、分度器ユーザーは何を発行しますか?
Bruno Bieri

57

非同期テストの場合でも、この場合はタイムアウトが発生します。制限タイムアウトの値を増やして非同期Jasmineコールバックを評価することにより、このエラーを回避できます

describe('Helper', function () {
    var originalTimeout;

    beforeEach(function() {
        originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
        jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000000;
    });

    afterEach(function() {
      jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
    });

    it('Template advance', function(doneFn) {
        $.ajax({
            url: 'public/your-end-point.mock.json',
            dataType: 'json',
            success: function (data, response) {
                // Here your expected using data
                expect(1).toBe(1)
                doneFn();
            },
            error: function (data, response) {
                // Here your expected using data
                expect(1).toBe(1)
                doneFn();
            }
        });
    });
});

ソース:http : //jasmine.github.io/2.0/introduction.html#section-42


1
これは「正しい方法」ではないように見えますが、私のSeleniumテストを実行するためにいくつかのゼロを追加した後、これは必要なハックでした。
エメリー

元のjasmine.DEFAULT_TIMEOUT_INTERVALは60000ミリ秒です。したがって、この例では実際には6倍短くなります。
Waltari 2018年


20

このエラーは、サービス/ファクトリーなどを初期化するときに注入を省略することによっても発生する可能性があります。たとえば、次のようにしてスローできます。

var service;
beforeEach(function(_TestService_) {
    service = _TestService_;
});

これを修正するには、関数をインジェクトでラップして、サービスを適切に取得します。

var service;
beforeEach(inject(function(_TestService_) {
    service = _TestService_;
}));

13
import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing';

fakeAsyncを使用する

beforeEach(fakeAsync (() => {

//your code

}));



describe('Intilalize', () => {
        it('should have a defined component', fakeAsync(() => {
            createComponent();
            expect(_AddComponent.ngOnInit).toBeDefined();
        }));
    });

6

あなたはカルマジャスミンを使うことができますプラグインを、デフォルトのタイムアウト間隔をグローバルに設定。

この構成をkarma.conf.jsに追加します

module.exports = function(config) {
  config.set({
    client: {
      jasmine: {
        timeoutInterval: 10000
      }
    }
  })
}

5

このエラーは、常に機能していたテストで、突然に始まりました。Macbookの動作が遅いことに気づくまで、役立つ提案は見つかりませんでした。CPUが別のプロセスによって停止されていることに気づき、それを強制終了しました。Jasmine非同期エラーが消え、私のテストは再び大丈夫です。

理由を聞かないでください、わかりません。しかし、私の状況では、障害のあるシステムリソースが不足しているように見えました。


5
おそらく、CPUが空いていたときに、タスクはデフォルトのタイムアウト前に終了しました。CPUがビジーのとき、テストしていたタスクが完了するまでに時間がかかりすぎました。
シェーン

5

これは回答というよりは観察結果ですが、私と同じように苛立っていた他の人を助けるかもしれません。

私は自分のスイートの2つのテストからこのエラーを受け取り続けました。私が行っていたリファクタリングでテストを単純に壊したのだと思ったので、変更を元に戻せなかった後、以前のコードに戻り、2回(2つのリビジョン戻って)、エラーがなくなると思いました。そうしても何も変わりませんでした。私は昨日一日中、そして今朝は問題を解決せずに尾を追いかけました。

今朝はイライラしてコードをラップトップにチェックアウトしました。テストスイート全体(約180テスト)を実行しましたが、エラーは発生しませんでした。したがって、エラーはコードやテストに含まれることはありません。私の開発ボックスに戻って再起動し、問題を引き起こしている可能性のあるメモリ内のすべてをクリアしました。変更なし、同じ2つのテストで同じエラー。だから私は自分のマシンからディレクトリを削除し、チェックアウトし直しました。出来上がり!エラーはありません。

何が原因なのか、またはどのように修正するのかはわかりませんが、作業ディレクトリを削除してチェックアウトすると、修正されました。

これが誰かを助けることを願っています。


1
ありがとう、私はこれに夢中になりました。私は自分のPCを再起動し、それはそれだけでした
yngrdyn

私の場合、コマンドを再実行しただけでこの問題は解決しました。ユニットテストのホットリロードを行ったところ、失敗していました。停止してコマンドを再度実行する必要がありました。
jignesh

4

は使用せずdone、関数呼び出しを空のままにしてください。


私が間違っている場合は修正してください。ただし、理解したとおり、テストの前にテストスイートが終了するだけで、エラーメッセージが代わりにダンプされます。つまり、アサートが実行される前にテストスイートが終了するため、失敗したアサートはテストを中断しません。また、別のテストでこのテストが作成したエラーが表示されることも意味します(同様の動作を見たことがあります)。最後に、最初はすべて問題ないように見えますが、テストの数が増えると、問題が断続的に表示されます。
LosManos

3

beforeAll関数で何かを期待しているときにもこのエラーが発生します!

describe('...', function () {

    beforeAll(function () {
        ...

        expect(element(by.css('[id="title"]')).isDisplayed()).toBe(true);
    });

    it('should successfully ...', function () {

    }
}

2

私の場合、このエラーは「fixture.detectChanges()」の不適切な使用が原因でした。このメソッドは、変更が検出されたときにのみコールバックに応答するイベントリスナー(非同期)のようです。変更が検出されない場合、コールバックは呼び出されず、タイムアウトエラーが発生します。お役に立てれば :)


2

scope参照と関数の引数を削除した後に機能します。

"use strict";

describe("Request Notification Channel", function() {
    var requestNotificationChannel, rootScope;

    beforeEach(function() {
        module("messageAppModule");

        inject(function($injector, _requestNotificationChannel_) {
            rootScope = $injector.get("$rootScope");
            requestNotificationChannel = _requestNotificationChannel_;
        })
        spyOn(rootScope, "$broadcast");
    });


    it("should broadcast delete message notification with provided params", function() {
        requestNotificationChannel.deleteMessage(1, 4);
        expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4} );
    });
});

0

@mastablastaで指摘されているように、「done」引数を呼び出すか、完了したという名前を付けた場合は、テストが完了したらコールバックcompleted()を呼び出すだけです。

// this block signature will trigger async behavior.
it("should work", function(done){
  // do stuff and then call done...
  done();
});

// this block signature will run synchronously
it("should work", function(){
  //...
});

0

jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;

これをブロックに保持することで、私の問題は解決しました。

it('', () => {
 jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
});

0

私がしたこと:次のコードを追加/更新しました:

framework: 'jasmine',
jasmineNodeOpts: 
{
    // Jasmine default timeout
    defaultTimeoutInterval: 60000,
    expectationResultHandler(passed, assertion) 
    {
      // do something
    },
}

3
説明なしで投稿するだけでなく、このコードが機能する理由を説明してください。
神戸

したがって、基本的にテストを実行して予想よりも時間がかかる場合、デフォルトのタイムアウトに達し、スクリプトが実行中に進まなかったため、テストは失敗します。これは、いくつかの条件が満たされていないために発生する可能性があります(可視性、ページのロードなど)。デフォルトのタイムアウトが1000msのような場合、>>は1秒でスクリプトが失敗することがよくあり、スクリプトの失敗には複数の要因が加わる可能性があります。ただし、タイムアウト間隔を長くすると、条件が満たされるまでブラウザ/ドライバが待機する時間が長くなる可能性があります。
Zeeshan

2
さて、あなたの投稿にそれを書いてください。説明なしでコードで答えるだけを避けるようにしてください:)
神戸


0

テストは決して来ないいくつかのコールバックを待っているようです。これは、テストが非同期動作で実行されないことが原因である可能性があります。

まず、「it」シナリオでfakeAsyncを使用しているかどうかを確認します。

it('should do something', fakeAsync(() => {

を使用flush()して、microTaskキューが完了するtick()まで待機するか、指定された時間待機することもできます。


-2

関数に引数(done)がある場合は、itそれも削除しようとします。関数自体の中で呼び出します。

it("should broadcast delete message notification", function(/*done -> YOU SHOULD REMOVE IT */) {

    requestNotificationChannel.deleteMessage(1, 4);
    expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4 });
    // done(); -> YOU SHOULD REMOVE IT        
});

4
なぜこの答えがそれほど役に立たないかについての説明なし。
Gary

2
この答えは私の問題を解決しました...角度テストは悪夢です!
Benjamin Caure
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.