jasmine: O retorno de chamada asynchronous não foi chamado dentro do tempo limite especificado por jasmine.DEFAULT_TIMEOUT_INTERVAL

Eu tenho um serviço angular chamado 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 }; }); 

Eu estou tentando unidade testar este serviço usando jasmine:

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

Eu li sobre o suporte asynchronous no Jasmine, mas como eu sou bastante novo para testes de unidade com javascript não poderia fazê-lo funcionar.

Estou recebendo um erro:

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

e meu teste está demorando muito para ser executado (cerca de 5s).

Alguém pode me ajudar fornecendo exemplo de trabalho do meu código com alguma explicação?

Ter um argumento em sua function fará com que ele tente uma chamada assíncrona.

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

Não faz diferença o nome do argumento, sua existência é tudo o que importa. Eu corri para esta questão de muita cópia / pasta.

Os documentos do Jasmin Asynchronous Support observam que o argumento (denominado done acima) é um retorno de chamada que pode ser chamado para permitir que Jasmine saiba quando uma function assíncrona é concluída. Se você nunca ligar, Jasmine nunca saberá que seu teste está pronto e acabará com o tempo limite.

Como solução alternativa, você pode aumentar o tempo limite para avaliar um retorno de chamada asynchronous do Jasmine

 describe('Helper', function () { var originalTimeout; beforeEach(function() { originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; }); 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(); } }); }); }); 

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

Este erro também pode ser causado por deixar de injetar ao inicializar um serviço / fábrica ou qualquer outra coisa. Por exemplo, pode ser jogado fazendo isso:

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

Para consertá-lo basta enrolar a function com injeção para recuperar corretamente o serviço:

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

use fakeAsync

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

Esse erro começou do nada para mim, em um teste que sempre funcionou. Eu não consegui encontrar nenhuma sugestão que ajudou até que eu notei que meu Macbook estava funcionando lentamente. Percebi que a CPU foi atrelada a outro processo, que matei. O erro async Jasmine desapareceu e meus testes estão bem novamente.

Não me pergunte porque, eu não sei. Mas na minha circunstância, parecia ser uma falta de resources do sistema em falta.

Você também recebe esse erro quando espera algo na function beforeAll !

 describe('...', function () { beforeAll(function () { ... expect(element(by.css('[id="title"]')).isDisplayed()).toBe(true); }); it('should successfully ...', function () { } } 

Funciona após remover a referência de scope e os argumentos da function:

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

No meu caso, este erro foi causado pelo uso indevido de “fixture.detectChanges ()” Parece que este método é um ouvinte de evento (async), que só responde a um retorno de chamada quando são detectadas alterações. Se nenhuma alteração for detectada, ela não chamará o retorno de chamada, resultando em um erro de tempo limite. Espero que isto ajude 🙂

Isso é mais uma observação do que uma resposta, mas pode ajudar outros que estavam tão frustrados quanto eu.

Eu continuei recebendo esse erro de dois testes na minha suíte. Eu pensei que tinha simplesmente quebrado os testes com a refatoração que eu estava fazendo, então depois de fazer as alterações não funcionarem, eu reverti para código anterior, duas vezes (duas revisões para trás) pensando que ele iria se livrar do erro. Fazer isso não mudou nada. Eu persegui minha cauda o dia todo ontem e parte desta manhã sem resolver o problema.

Eu fiquei frustrado e verifiquei o código em um laptop esta manhã. Ran o conjunto de testes inteiro (cerca de 180 testes), sem erros. Portanto, os erros nunca estavam no código ou nos testes. Voltei para minha checkbox dev e reiniciei para limpar qualquer coisa na memory que possa estar causando o problema. Nenhuma mudança, os mesmos erros nos mesmos dois testes. Então eu apaguei o diretório da minha máquina e verifiquei de novo. Voila! Sem erros.

Não faço ideia do que causou isso, ou como consertá-lo, mas excluindo o diretório de trabalho e verificando-o de volta fixo o que quer que fosse.

Espero que isso ajude alguém.

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