jasmine: jasmine.DEFAULT_TIMEOUT_INTERVAL tarafından belirtilen zaman aşımı süresi içinde zaman uyumsuz geri çağrı çağrılmadı


141

Açılı bir hizmet var 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
    };

});

Yasemin kullanarak bu hizmeti birim test etmeye çalışıyorum:

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

Yasemin'deki Asenkron Destek hakkında okudum, ancak javascript ile birim testi yapmak için yeni olduğum için bunu çalıştıramadım.

Bir hata alıyorum:

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

ve testimin yürütülmesi çok uzun sürüyor (yaklaşık 5 saniye).

Birisi kodumun çalışma örneğini biraz açıklamama yardımcı olabilir mi?


1
Olayları işleme genellikle özet döngüsünde yapılır. Kapsam eklemeyi deneyin. Jasmine'in eşzamansız test desenini kullanmak yerine testinize $ Apply ()
Eitan Peer

bu işe yaramadı. Kapsam ekledim. $ Apply (); requestNotificationChannel.deleteMessage (1, 4) çağırdıktan hemen sonra ama aynı hatayı alıyorum ...
Mdb

Ben aynı hatayı alıyorum zaman uyumsuz testler daha çalıştırmak için uzun sürer Jestbeklentiden ayıklama ve değişkenleri incelemek için biraz zaman çekerken çok yaygın -.
Dan Dascalescu

Bunun yerine daha az zaman aşımı kullanmayı deneyin. Zaman aşımı = 5000 kullanırken bu hatayı aldım. 2000 ile değiştirdim ve benim için çalıştı!
Marina Riaz

1
Ayakkabılarımdaki birine yardım etmek için burayı bırakıyorum. Bir docker kapsayıcısının içindeki testleri çalıştırırken bu hatayla karşılaştım. Testler bazen sorunsuz geçse de bazen başarısız olur. Bir çeşit yarış durumu olduğunu düşündüm ama nedenini bulamadım. Ben afterEach( deleteManyyöntemi kullanarak ) veritabanını temizlemek bir adım olduğunu fark ettim . Ekleme jest.setTimeout(30000);içinde beforeAllyönteme benim için sabit gibi görünüyor - veritabanı silme (koşul içinde) bir ağ çağrısı beri, bazen 3 saniye ve atma uzun sürüyor tahmin ediyorum.
nkhil

Yanıtlar:


231

itİşlevinizde bir argüman bulunması ( doneaşağıdaki kodda), Jasmine'in zaman uyumsuz çağrı yapmasına neden olur.

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

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

doneArgümanın isminin bir farkı yoktur , varlığı önemlidir. Bu konuya çok fazla kopya / makarnadan rastladım.

Jasmine Eşzamansız Destek belgeleri, argümanın ( doneyukarıda adı geçen), eşzamansız bir işlev tamamlandığında Yasemin'e haber vermek için çağrılabilen bir geri arama olduğunu not eder . Hiç aramazsanız, Yasemin testinizin yapıldığını asla bilemez ve sonunda zaman aşımına uğrar.


3
Aynı şey, açıklamadaki args için de geçerlidir (açısal olarak, bunu yapmak için inject
inject'i çağırmanız gerekir

@MartinBliss Belgelendirildi, belgelere başvurmak için bir düzenleme önerdim: stackoverflow.com/suggested-edits/2434606
Vincent

39
Gelecekte bu soruya rastlayan rastgele Google çalışanlarına dikkat edin: İletki kullanıyorsanız ve bu sorunla karşılaşırsanız, bu cevap aradığınız şey değildir - İletki geri aramayı kendi başına çağırır.
Vincent

Sorunumu düzeltti ve aynı cuplrit "kopya / makarna" neden oldu
shaikh

1
@Vincent Bu hata oluşursa İletki kullanıcıları sorunu nedir?
Bruno Bieri

57

Eşzamansız testler için bile, bu durumlarda sönen bir zaman aşımı vardır.

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

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


1
Bu, bunu yapmak için "doğru yol" gibi görünmüyor, ancak Selenyum testimin çalışması için birkaç ekstra sıfır ekledikten sonra, bu gerekli bir kesmekti.
emery

Orijinal yasemin.DEFAULT_TIMEOUT_INTERVAL 60000 ms'dir. Yani bu örnek aslında altı kat daha kısa yapacaktır.
Waltari

Haklısın, sadece bu örnekte rastgele bir sayı koydum, teşekkürler :)
gsalgadotoledo

20

Bu hata, bir hizmeti / fabrikayı başlatırken veya herhangi bir şekilde enjekte edilmemesinden de kaynaklanabilir. Örneğin, bunu yaparak atılabilir:

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

Düzeltmek için, hizmeti düzgün bir şekilde almak için enjekte işlevini sarmanız yeterlidir:

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

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

fakeAsync kullanın

beforeEach(fakeAsync (() => {

//your code

}));



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

6

Sen kullanabilirsiniz karma-yasemin aralık küresel olarak dışarı varsayılan süreyi ayarlamak için eklenti.

Bu yapılandırmayı karma.conf.js dosyasına ekleyin

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

5

Bu hata benim için her zaman işe yaramış bir testte başladı. Macbook'umun yavaş çalıştığını fark edene kadar herhangi bir öneri bulamadım. CPU'nun öldürdüğüm başka bir işlem tarafından tespit edildiğini fark ettim. Yasemin eşzamansız hatası kayboldu ve testlerim bir kez daha iyi.

Bana nedenini sorma, bilmiyorum. Ama benim durumumda, hatalı sistem kaynaklarının eksikliği gibi görünüyordu.


5
Muhtemelen, CPU'nuz serbest olduğunda, görev varsayılan zaman aşımından önce sona erdi. CPU meşgulken test ettiğiniz görevin tamamlanması çok uzun sürdü.
Shane

5

Bu bir cevaptan çok bir gözlemdir, ama benim kadar hayal kırıklığına uğramış olan diğer insanlara yardımcı olabilir.

Bu hatayı paketimdeki iki testten almaya devam ettim. Yaptığım refactoring ile testleri kırdığımı sanıyordum, bu yüzden değişiklikleri geri aldıktan sonra işe yaramadı, önceki kodlara döndüm, iki kez (iki düzeltme geri) hatadan kurtulacağını düşündüm. Bunu yapmak hiçbir şeyi değiştirmedi. Dün bütün gün kuyruğumu kovaladım ve bu sabah bir kısmı sorunu çözmeden kovaladım.

Hayal kırıklığına uğradım ve bu sabah bir dizüstü bilgisayar kodunu kontrol ettim. Tüm test paketini çalıştırın (yaklaşık 180 test), hata yok. Yani hatalar asla kodda veya testlerde yoktu. Geliştirme kutuma geri döndüm ve bellekteki soruna neden olabilecek herhangi bir şeyi temizlemek için yeniden başlattı. Değişiklik yok, aynı iki testte aynı hatalar. Bu yüzden dizini makinemden sildim ve tekrar kontrol ettim. İşte bu kadar! Hata yok.

Buna neyin sebep olduğu veya nasıl düzeltileceği hakkında hiçbir fikrim yok, ancak çalışma dizinini silmek ve kontrol etmek, ne olursa olsun düzeltildi.

Umarım bu birine yardımcı olur.


1
Teşekkürler dostum, bu konuda deliriyordum. Bilgisayarımı yeniden
başlattım

Benim durumumda, sadece komutu yeniden çalıştırdım ve bu sorunu çözdü. Birim testleri için sıcak yeniden yükleme vardı ve her zaman başarısız oldu. Komutu tekrar durdurmak ve çalıştırmak zorunda kaldım.
jignesh

4

Kullanmayın done, sadece işlev çağrısını boş bırakın.


Yanılıyorsam lütfen beni düzeltin ama anladığım kadarıyla test paketini çok testten önce bitiriyor ve hata mesajı yerine dökülüyor. Başka bir deyişle, başarısız olan herhangi bir iddia, onaylama çalıştırılmadan önce test takımı tamamlandıkça testi kırmaz. Aynı zamanda (benzer davranışlar gördüm) başka bir testin bu testin oluşturduğu hatayı gösterdiği anlamına gelebilir. Son olarak, her şey başlamak için iyi görünüyor, ancak test sayısı arttıkça sorun aralıklı olarak ortaya çıkacak.
LosManos

3

Ayrıca beforeAllfonksiyonda bir şey beklerken bu hatayı alırsınız !

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

    beforeAll(function () {
        ...

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

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

    }
}

2

Benim durumumda, bu hata "fixture.detectChanges ()" yanlış kullanımı nedeniyle bu yöntem, sadece değişiklikler algılandığında bir geri çağrı yanıt verecektir bir olay dinleyicisi (zaman uyumsuz) gibi görünüyor. Herhangi bir değişiklik algılanmazsa, geri çağrıyı başlatmaz ve zaman aşımı hatasına neden olur. Bu yardımcı olur umarım :)


2

scopeBaşvuru ve işlev bağımsız değişkenlerini kaldırdıktan sonra çalışır :

"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 tarafından belirtildiği gibi, aynı zamanda 'tamamlanmış' argümanını çağırırsanız ya da tamamladığını isimlendirirseniz, tamamlandığında testinizde tamamlanmış () geri çağrıyı çağırmanız yeterlidir .

// 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

yasemin.DEFAULT_TIMEOUT_INTERVAL = 100000;

Bunu blokta tutmak sorunumu çözdü.

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

0

Ne yaptım: Eklendi / Aşağıdaki kodu güncelledi:

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

3
Lütfen bu kodun açıklama yapmadan yayınlamak yerine neden çalıştığını açıklayın.
Kobe

Temel olarak bir testi yürüttüğünüzde ve beklenenden daha uzun sürdüğünde, varsayılan zaman aşımı karşılandığı ve komut dosyasının yürütmede ilerlemediği için başarısız olur. Bu, karşılanmayan bazı koşullar nedeniyle olabilir (Örneğin görünürlük, sayfa yükleme). Şimdi varsayılan zaman aşımı 1000 ms gibi ise >> betikler sık ​​sık başarısız olur çünkü bu sadece bir saniye ve betiğinizin başarısızlığına birçok faktör eklenebilir. Bununla birlikte, zaman aşımı aralığınızı artırmak, koşulların karşılanması için tarayıcıyı / sürücüyü daha uzun süre bekletebilir.
Zeeshan

2
Tamam, şimdi bunu yazının içine yaz; sadece açıklama yapmadan kodla cevap vermekten kaçınmalısınız :)
Kobe

0

Onun yerine

beforeEach(() => {..

kullanım

beforeEach(fakeAsync(() => {..

0

Test hiç gelmeyecek bir geri arama bekliyor gibi görünüyor. Bunun nedeni, testin eşzamansız davranışla yürütülmemesidir.

İlk olarak, "it" senaryosunda sadece fakeAsync'in kullanılıp kullanılmadığına bakın:

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

Ayrıca flush(), microTask kuyruğunun bitmesini tick()beklemek veya belirli bir süre beklemek için de kullanabilirsiniz .


-2

İşlevde bir argüman ( done) varsa, itonu da kaldırmaya çalışın, işlev içinde çağrılır:

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
Bu cevabın neden bu kadar yararlı olmadığını açıklamaksızın.
Gary

2
bu cevap sorunumu çözdü ... açısal test bir kabus!
Benjamin Caure
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.