jasmine: Callback Async tidak dipanggil dalam batas waktu yang ditentukan oleh jasmine.DEFAULT_TIMEOUT_INTERVAL

140

Saya memiliki layanan sudut bernama 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
    };

});

Saya mencoba untuk menguji layanan ini menggunakan melati:

"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();       
    });
});

Saya membaca tentang Dukungan Asinkron di Jasmine, tetapi karena saya agak baru dalam pengujian unit dengan javascript tidak dapat membuatnya berfungsi.

Saya menerima kesalahan:

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

dan pengujian saya terlalu lama untuk dijalankan (sekitar 5s).

Adakah yang bisa membantu saya memberikan contoh kerja kode saya dengan beberapa penjelasan?

Mdb
sumber
1
Acara pengolahan biasanya dilakukan dalam siklus intisari. Coba tambahkan cakupan. $ Apply () ke pengujian Anda alih-alih menggunakan pola pengujian async Jasmine
Eitan Peer
ini tidak berhasil. Saya menambahkan ruang lingkup. $ Apply (); tepat setelah memanggil requestNotificationChannel.deleteMessage (1, 4) tapi saya menerima kesalahan yang sama ...
Mdb
Saya mendapatkan kesalahan yang sama ketika tes async membutuhkan waktu lebih lama untuk dijalankan daripada yang Jestdiharapkan - sangat umum saat debugging dan meluangkan waktu untuk memeriksa variabel.
Dan Dascalescu
Coba gunakan timeout yang lebih rendah. Saya mendapatkan kesalahan ini saat menggunakan batas waktu = 5000. Saya menggantinya dengan 2000 dan berhasil bagi saya!
Marina Riaz
1
Meninggalkan ini di sini untuk membantu seseorang di sepatuku. Saya memiliki kesalahan ini saat menjalankan tes di dalam wadah buruh pelabuhan. Tes terkadang lulus tanpa masalah, tetapi terkadang gagal. Saya pikir itu semacam kondisi balapan tetapi tidak tahu mengapa. Saya menyadari bahwa saya memiliki afterEachlangkah yang membersihkan database (menggunakan deleteManymetode). Menambahkan jest.setTimeout(30000);dalam beforeAllmetode ini tampaknya telah memperbaiki ini untuk saya - saya menduga karena penghapusan basis data adalah panggilan jaringan (di dalam kondisi), kadang-kadang membutuhkan waktu lebih dari 3 detik dan melempar.
nkhil

Jawaban:

231

Memiliki argumen dalam itfungsi Anda ( donedalam kode di bawah) akan menyebabkan Jasmine mencoba melakukan panggilan async.

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

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

Tidak ada bedanya apa nama doneargumen itu, keberadaannya adalah yang terpenting. Saya mengalami masalah ini karena terlalu banyak salin / pasta.

Dokumen Dukungan Jasmine Asynchronous mencatat bahwa argumen (disebutkan di doneatas) adalah panggilan balik yang dapat dipanggil untuk memberi tahu Jasmine ketika fungsi asinkron selesai. Jika Anda tidak pernah menyebutnya, Jasmine tidak akan pernah tahu tes Anda selesai dan pada akhirnya akan habis.

mastaBlasta
sumber
3
Hal yang sama berlaku untuk args dalam uraian (dalam sudut, Anda perlu memanggil inject dalam uraikan untuk melakukan itu)
Narretz
@ MartinBliss Sudah didokumentasikan, saya baru saja menyarankan mengedit untuk merujuk ke dokumentasi: stackoverflow.com/suggested-edits/2434606
Vincent
39
Catatan untuk Googler acak menemukan pertanyaan ini di masa depan: jika Anda menggunakan busur derajat dan mengalami masalah ini, jawaban ini bukan yang Anda cari - Busur Derajat memanggil panggilan balik dengan sendirinya.
Vincent
Itu memperbaiki masalah saya dan itu disebabkan oleh "copy / pasta" cuplrit yang sama
shaikh
1
@Incent apa masalah pengguna busur derajat lalu jika kesalahan ini terjadi?
Bruno Bieri
57

Bahkan untuk tes async, ada batas waktu yang padam dalam kasus ini, Anda bisa mengatasi kesalahan ini dengan meningkatkan nilai batas waktu batas untuk mengevaluasi panggilan balik Jasmine async

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();
            }
        });
    });
});

Sumber: http://jasmine.github.io/2.0/introduction.html#section-42

gsalgadotoledo
sumber
1
Ini sepertinya bukan "cara yang tepat" untuk melakukannya, tetapi setelah menambahkan beberapa nol ekstra untuk menjalankan tes Selenium saya, ini adalah peretasan yang diperlukan.
Amril
Melati asli.DEFAULT_TIMEOUT_INTERVAL adalah 60000 ms. Jadi contoh ini sebenarnya akan membuatnya enam kali lebih pendek.
Waltari
Anda benar, saya hanya memasukkan angka acak dalam contoh ini, terima kasih :)
gsalgadotoledo
20

Kesalahan ini juga dapat disebabkan oleh tidak menyuntikkan saat menginisialisasi layanan / pabrik atau apa pun. Sebagai contoh, itu dapat dibuang dengan melakukan ini:

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

Untuk memperbaikinya cukup bungkus fungsi dengan menyuntikkan untuk mengambil layanan dengan benar:

var service;
beforeEach(inject(function(_TestService_) {
    service = _TestService_;
}));
Katana24
sumber
13
import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing';

gunakan fakeAsync

beforeEach(fakeAsync (() => {

//your code

}));



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

Anda dapat menggunakan plugin karma-jasmine untuk mengatur interval waktu default secara global.

Tambahkan konfigurasi ini di karma.conf.js

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

Kesalahan ini berawal dari saya, pada tes yang selalu berhasil. Saya tidak dapat menemukan saran yang membantu sampai saya perhatikan Macbook saya berjalan lamban. Saya perhatikan CPU dipatok oleh proses lain, yang saya bunuh. Kesalahan Jasmine async menghilang dan tes saya baik-baik saja sekali lagi.

Jangan tanya kenapa, saya tidak tahu. Tetapi dalam keadaan saya tampaknya kekurangan sumber daya sistem kesalahan.

Eric Soyke
sumber
5
Mungkin, ketika CPU Anda bebas, tugas selesai sebelum batas waktu default. Saat CPU sedang sibuk, tugas yang Anda uji terlalu lama untuk diselesaikan.
Shane
5

Ini lebih merupakan pengamatan daripada jawaban, tetapi mungkin membantu orang lain yang sama frustrasinya dengan saya.

Saya terus mendapatkan kesalahan ini dari dua tes di suite saya. Saya pikir saya baru saja memecahkan tes dengan refactoring yang saya lakukan, jadi setelah mencadangkan perubahan tidak berhasil, saya kembali ke kode sebelumnya, dua kali (dua revisi kembali) berpikir itu akan menghilangkan kesalahan. Melakukan hal itu tidak mengubah apa pun. Saya mengejar ekor saya sepanjang hari kemarin, dan sebagian pagi ini tanpa menyelesaikan masalah.

Saya merasa frustrasi dan memeriksa kode ke laptop pagi ini. Jalankan seluruh test suite (sekitar 180 tes), tidak ada kesalahan. Jadi kesalahan tidak pernah ada dalam kode atau tes. Kembali ke kotak dev saya dan mem-boot ulang untuk menghapus semua yang ada di memori yang mungkin menyebabkan masalah. Tidak ada perubahan, kesalahan yang sama pada dua tes yang sama. Jadi saya menghapus direktori dari mesin saya, dan memeriksanya kembali. Voila! Tidak ada kesalahan

Tidak tahu apa yang menyebabkannya, atau bagaimana cara memperbaikinya, tetapi menghapus direktori kerja dan memeriksanya tetap apa pun itu.

Semoga ini bisa membantu seseorang.

delliottg
sumber
1
Terima kasih kawan, aku sudah gila tentang ini. Saya reboot PC saya dan hanya itu
yngrdyn
Dalam kasus saya, saya hanya menjalankan kembali perintah dan menyelesaikan masalah ini. Saya memiliki reload panas untuk unit-tes dan setiap kali gagal. Saya harus berhenti dan menjalankan perintah lagi.
jignesh
4

Jangan gunakan done, biarkan saja fungsi panggilan kosong.

Anastasiia Semionova
sumber
Tolong perbaiki saya jika saya salah tetapi karena saya mengerti itu hanya membuat test suite selesai sebelum tes dan dan pesan kesalahan dibuang sebagai gantinya. Yang berarti bahwa setiap pernyataan yang gagal tidak akan merusak tes karena paket tes selesai sebelum pernyataan dijalankan. Mungkin juga berarti (saya telah melihat perilaku serupa) bahwa tes lain menunjukkan kesalahan yang dibuat oleh tes ini. Akhirnya itu berarti bahwa semuanya terlihat baik-baik saja untuk memulainya tetapi karena jumlah tes tumbuh masalah akan muncul sebentar-sebentar.
LosManos
3

Anda juga mendapatkan kesalahan ini saat mengharapkan sesuatu di beforeAllfungsi!

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

    beforeAll(function () {
        ...

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

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

    }
}
Tom Van Rossom
sumber
2

Dalam kasus saya, kesalahan ini disebabkan oleh penggunaan yang tidak benar dari "fixture.detectChanges ()" Tampaknya metode ini adalah pendengar acara (async) yang hanya akan merespons panggilan balik ketika perubahan terdeteksi. Jika tidak ada perubahan yang terdeteksi, itu tidak akan memanggil balik, menghasilkan kesalahan waktu habis. Semoga ini membantu :)

A. Figueroa
sumber
2

Bekerja setelah menghapus scopereferensi dan argumen fungsi:

"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} );
    });
});
Paul Sweatte
sumber
0

Seperti dicatat oleh @mastablasta, tetapi juga untuk menambahkan bahwa jika Anda memanggil argumen 'selesai' atau lebih tepatnya nama itu selesai Anda hanya memanggil panggilan balik selesai () dalam pengujian Anda ketika sudah selesai.

// 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(){
  //...
});
SoEzPz
sumber
0

jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;

Menjaga ini di blok memecahkan masalah saya.

it('', () => {
 jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
});
Sai Prasad
sumber
0

Apa yang saya lakukan adalah: Menambahkan / Memperbarui kode berikut:

framework: 'jasmine',
jasmineNodeOpts: 
{
    // Jasmine default timeout
    defaultTimeoutInterval: 60000,
    expectationResultHandler(passed, assertion) 
    {
      // do something
    },
}
Zeeshan
sumber
3
Tolong jelaskan mengapa kode ini berfungsi, bukan hanya mempostingnya tanpa penjelasan.
Kobe
Jadi pada dasarnya ketika Anda menjalankan tes dan butuh waktu lebih lama dari yang diharapkan, itu gagal karena batas waktu default terpenuhi dan skrip tidak bergerak maju dalam eksekusi. Ini bisa terjadi karena beberapa kondisi tidak terpenuhi (Misalnya visibilitas, pemuatan halaman). Sekarang jika batas waktu default Anda seperti skrip 1000ms >> akan sering gagal karena hanya satu detik dan mungkin ada beberapa faktor yang menambah kegagalan skrip Anda. Namun, meningkatkan interval waktu habis Anda dapat membuat browser / driver menunggu lebih lama untuk memenuhi kondisi.
Zeeshan
2
Oke, sekarang kata itu ke posting Anda; Anda harus mencoba untuk menghindari hanya menjawab dengan kode tanpa penjelasan :)
Kobe
0

Dari pada

beforeEach(() => {..

menggunakan

beforeEach(fakeAsync(() => {..
Meghnath Das
sumber
0

Sepertinya tes sedang menunggu panggilan balik yang tidak pernah datang. Kemungkinan karena tes tidak dijalankan dengan perilaku asinkron.

Pertama, lihat apakah hanya menggunakan fakeAsync dalam skenario "it" Anda:

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

Anda juga dapat menggunakan flush()untuk menunggu antrian microTask selesai atau tick()menunggu sejumlah waktu tertentu.

Shapeshifter
sumber
-2

Jika Anda memiliki argumen ( done) dalam itfungsi, cobalah untuk menghapusnya dan itu juga panggilan dalam fungsi itu sendiri:

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        
});
tiagor87
sumber
4
Tanpa penjelasan mengapa jawaban ini tidak berguna.
Gary
2
jawaban ini memecahkan masalah saya ... pengujian sudut adalah mimpi buruk!
Benjamin Caure