Jest: O processo de Jest não termina após a conclusão do último teste

Criado em 18 ago. 2016  ·  60Comentários  ·  Fonte: facebook/jest

Estou tendo problemas com o processo Jest não concluído após a conclusão do último teste. O usuário terá que forçar o encerramento do processo com ctrl-c. Minha teoria é que nem todos os recursos estão sendo limpos de forma adequada pelos autores do teste, mas o ideal é que Jest pare de qualquer maneira.

Especificamente, estou testando o Firebase com firebase-server , girando um ou mais servidores para cada teste. Em uma ação afterEach chamamos o método close para todos os servidores criados no último teste, porém mesmo com este método o processo de Jest ainda não termina.

Existe uma maneira de forçar o encerramento do processo de Jest depois que os testes forem concluídos (aprovação ou reprovação)? Existe uma maneira de obter um gancho afterAll para limpar todos os recursos restantes? Existe uma maneira de depurar o que exatamente impede o processo de Jest de encerrar? Obrigado.

Enhancement Help Wanted good first issue

Comentários muito úteis

para qualquer pessoa que esteja lendo, você pode usar a bandeira --forceExit para acessar essa funcionalidade. 🎉

Todos 60 comentários

Não temos uma boa maneira de fazer isso agora. Eu recomendaria tentar conectar um depurador (Chrome Inspector) para descobrir o que está acontecendo. Se você sabe o que cria o trabalho assíncrono, pode potencialmente também fazer um monkey patch e rastreá-lo (como colocar algo em torno de Promise.prototype.then)

Existe um motivo pelo qual o trabalho assíncrono não pode ser encerrado à força quando todos os ganchos afterEach / after foram resolvidos?

Eu não sei como você mataria os processos assíncronos existentes se você não tivesse um controle sobre eles.

Eu migrei de ava e isso não foi um problema, talvez haja uma resposta? Talvez seja process.exit em Node.js

Nós poderíamos fazer isso, eu acho, mas estou preocupado que isso deixe as pessoas não esperando quando deveriam e elas não estejam fechando seus recursos adequadamente.

cc @dmitriiabramov o que você acha?

Um exemplo: eu na verdade me deparei com isso com Jest, onde tínhamos um longo processo de observador que não encerraria o próprio Jest. Se Jest tivesse se suicidado durante a execução do teste (heh!), Eu nunca teria percebido o problema e teria enviado uma versão que travaria quando as pessoas tentassem usá-la.

não tenho certeza se é seguro forçar o encerramento do processo. ao mesmo tempo, se as pessoas quiserem fazer algum pós-processamento assíncrono depois que os testes forem concluídos, elas podem usar after all gancho que irá esperar que termine antes de encerrar o processo.

o outro problema que podemos ter é cortar o fluxo de saída antes de terminar a impressão. já tivemos esse problema antes, quando as mensagens de erro não têm tempo suficiente para imprimir antes que o processo seja encerrado.

A questão é se poderíamos descobrir uma maneira de Jest dizer "Parece que alguns testes não estão se limpando. Aqui está o que está acontecendo".

Um gancho after all poderia me ajudar aqui, mas eu não vi tal coisa na documentação (apenas afterEach ) estou faltando alguma coisa?

Quanto ao teste de limpezas corretas, se você pudesse testar se os _files_ foram concluídos no prazo e se não estavam usando um recurso de bisect para isolar o problema (como no rspec).

Ok, então, depois de mais pesquisas, isso parece ser um problema com o Firebase em si, e não há maneira de limpar sem chamar process.exit .

Recursos:

Todas as soluções alternativas envolvem chamar manualmente process.exit . Tenho medo de fazer isso em um contexto de brincadeira. Existe uma recomendação sobre onde fazer essa chamada? Meu primeiro pensamento foi algo como:

afterAll(() => setTimeout(() => process.exit(), 1000))

… Para sair um segundo depois que todos os testes terminarem de executar para permitir que Jest faça seu trabalho, no entanto, não tenho certeza de como isso afeta o modo de observação e, se estiver correto, Jest faz algumas coisas fantasiosas de paralelismo que podem fazer isso não funcionar como esperado. Alternativamente, isso seria algo que você precisa corrigir no Jest adequado? Se isso parece uma metralhadora para várias pessoas, por que não colocá-la no Jest? Ou pelo menos alternar entre o modo “avisar” e o modo “matar”.

Eu adoraria uma bandeira --exit ou algo (pode ser um comentário por arquivo ou algo assim) que fecha automaticamente os processos quando os testes são concluídos, semelhante ao mocha. é um pouco chato fechar manualmente todas as conexões em todos os arquivos de teste.

Estou tendo o mesmo problema quando executo testes no Codeship . Ele também falha em drone.io .
Porém, localmente, ele funciona corretamente.

EDITAR:

  • Versão Jest : 15.1.1
  • Local :

    • Nó: 6.2.2

    • npm: 3,9,5

  • CodeShip :

    • Nó: 6.5.0

    • npm: 3.10.3

  • Drone.io

    • Nó: 0.10.26

    • npm: 1.4.3

Parece-me que o Firebase deve ser corrigido.

Não tenho reservas contra adicionar uma opção chamada --forceExitAfterTestRun e deve ser fácil de adicionar. Acho que só requer uma mudança para sair aqui: https://github.com/facebook/jest/blob/master/packages/jest-cli/src/cli/index.js#L41 se o sinalizador for fornecido independentemente do resultado.

Parece ser uma espécie de condição de corrida. Às vezes, ele fecha depois de executar todos os testes localmente, às vezes não ...

Também estou executando isso depois de começar a usar Jest para minhas especificações de API, onde estou usando banco de dados real em vez de simulações (desculpe, mas instantâneos são ótimos para isso). Eu ainda fui capaz de resolver o problema mesmo depois de adicionar afterAll ganchos para limpar as conexões, o que me leva a acreditar que é de alguma forma relacionado à minha população de acessórios em setupFiles , não o mais fácil de depurar.

Jasmine parece ter a opção de --forceexit então eu não reclamaria se semelhante também caísse para Jest 🙏

outro problema - se um teste falhar, então afterAll() não é chamado, então nada é limpo e nada fecha. Acho que --bail vai consertar isso, mas ainda não tentei

Se alguém quiser enviar um PR, precisamos de ajuda para isso e eu delineei os detalhes em meu comentário anterior :)

Vou tentar se tiver algum tempo no fim de semana. Se alguém quiser fazer antes, ótimo: sorria:

Fechando a favor do PR que acaba de inaugurar. Continuaremos a discussão lá.

para qualquer pessoa que esteja lendo, você pode usar a bandeira --forceExit para acessar essa funcionalidade. 🎉

Para googlers: Jest não sai do Jenkins CI, mas sim localmente .. --forceExit corrigiu para mim.

Para mim, foi esquecer de lidar com a promessa com .then (() => {}) - deu certo

Eu ainda estou lutando com isso. Estou testando uma API com async e await . Eu me conecto ao meu aplicativo expresso e faço ping em um endpoint, mas o teste não fecha. Tentei fechar a conexão com o mongodb e com o servidor, mas ainda está aberta. Estou apenas enviando de volta json vazio.

No meu caso, isso acabou sendo um problema do Firebase. Usando

afterAll(() => {
  firebaseApp.database().goOffline();
  firebaseApp.delete();
});

parece fazer o truque. Descobri que ambas as linhas são realmente necessárias e que você precisa usar o mesmo firebaseApp que obteve originalmente de .initializeApp() .

Existe alguma maneira de resolver isso sem forceExit?

Jest 23 inclui uma bandeira chamada --detectOpenHandles que deve apontar para a fonte de porque Jest não pode sair

--detectOpenHandles retorna mongoose.connect e mongoose.model. A tentativa de mongoose.disconnect em afterAll gera um erro de mongo Topologia destruída.

screenshot 2018-06-08 11 14 51
screenshot 2018-06-08 11 14 29

@elkhan você descobriu como resolver os problemas do mangusto?

Depois de adicionar --detectOpenHandles , Jest não apenas completa meus testes como também não mostra nada que bloqueie Jest, o que é estranho. Parece um bug.

Para mim, --forceExit resolve o problema, ao mesmo tempo eu uso --detectOpenHandles mas ele não detecta nada (localmente e no CircleCI). Também estou trabalhando com --runInBand .

Para mim, remover --runInBand resolveu.

--forceExit resolve o problema para mim também quando se usa shippable ... Tentei --detectOpenHandles , mas não deu qualquer resultado e ainda assim causou a compilação jeito

Adicionar --detectOpenHandles corrige o problema, que é bizarro.

Nó: v8.12.0
Jest: v23.6.0

Adicionar --detectOpenHandles ou --forceExit não resolve o problema para mim ao executar no Codeship.

jest --ci --verbose --forceExit --detectOpenHandle

Nó: v8.12.0
Jest: v23.6.0

@sibelius uma maneira de evitar este problema é silenciar a função init do modelo

const mongoose = require('mongoose');

mongoose.Model.init = () => {};

Isso fará com que Jest pare de reclamar dos modelos, embora os índices não sejam criados

db.collection("test-collection").add({
    title: 'post title',
    content: 'This is the test post content.',
    date: new Date(),
})
    .then(docRef => {
        console.log('Document written with ID: ', docRef);
    })
    .catch(error => {
        console.error('Error adding document: ', error);
    });

jest --forceExit --detectOpenHandle os testes foram aprovados, mas o código em .then ou .catch não foi executado !!
alguma ideia?

@alexpchin Veja como eu resolvi:

    beforeAll(async (done) => {
        dbConnection = await mongoose.connect(...)
        done()
    })

    afterAll(async (done) => {
        await dbConnection.close()
        dbConnection.on('disconnected', done)
    })

Com NestJs eu tive que adicionar

afterAll(() => {
  app.close();
});

Descobrimos que esse problema foi causado por falta de memória do processo jest. Adicionar --maxWorkers=10 corrigiu o problema para nós.

Estou adicionando esta causa, talvez alguém que esteja se perguntando sobre esse problema possa estar tendo a razão para isso como eu.
Eu estava usando Jest dentro do Travis para testar um aplicativo NodeJS e travis continuou pendurado até o tempo limite, logo após Jest. Parece que Jest não estava fechando.
Depois de muitas tentativas, descobri que o motivo era usar o jest com JSDom.
Eu tinha a seguinte linha em meu arquivo jest.config.js :

  'testURL': 'http://localhost/',

O que fez com que o JSDom carregasse e, supostamente, não fechasse todos os recursos normalmente e mantendo Jest vivo.

Eu resolvi isso removendo a linha - no entanto, Jest irá falhar com o seguinte erro, veja isto :

SecurityError: localStorage is not available for opaque origins

Para resolver, adicionei o seguinte a jest.config.js :

  'testEnvironment': 'node',

Espero que ajude alguém. Estou adicionando esta causa, talvez alguém que esteja se perguntando sobre esse problema possa ter a razão para isso como eu.
Eu estava usando o Jest dentro do Travis para testar um aplicativo NodeJS e travis continuou pendurado até o tempo limite logo após o Jest. Parece que Jest não estava fechando.
Depois de muitas tentativas, descobri que o motivo era usar o jest com JSDom.
Eu tinha a seguinte linha no meu arquivo jest.config.js :

  'testURL': 'http://localhost/',

O que fez com que o JSDom carregasse e, supostamente, não fechasse todos os recursos normalmente e mantendo Jest vivo.

Eu resolvi removendo a linha - no entanto, Jest irá falhar com o seguinte erro, veja isto :

SecurityError: localStorage is not available for opaque origins

Para resolver, adicionei o seguinte a jest.config.js :

  'testEnvironment': 'node',

Espero que ajude alguém.

--forceExit --detectOpenHandles --maxWorkers = 10

fez isso por nós

nó: 8.11.3
jest 23.6.0

Com NestJs eu tive que adicionar

afterAll(() => {
  app.close();
});

Só deixando isso aqui para o pessoal do NestJS:
Com o NestJS, descobri que a resposta acima funciona.
O que NÃO funciona é o seguinte:

afterAll(async () => {
        await app.close()
    })

para mim, é --forceExit --maxWorkers=10 que funciona (estou no Ubuntu 18.04, usando [email protected])

No meu caso, usar o NodeJS 10 ou 11 corrige o problema, mas ainda está lá com o Node 6 ou o Node 8. nada é exibido ao usar a opção --detectOpenHandles e --forceExit corrige o problema.

Mais 1 pessoa aqui (como @motss e @seanlindo ) observando que _ "Jest não saiu um segundo após a execução do teste ser concluída." _ Ocorre apenas quando --detectOpenHandles não é usado.

[email protected]

Os testes falham consistentemente sem --detectOpenHandles mas passam e não mostram nenhuma alça aberta quando executados com --detectOpenHandles .

A máquina / contêiner que executa os testes tem dois núcleos, mas por padrão, os testes são executados com maxWorkers=1

Quando adiciono a sinalização --detectOpenHandles e vejo config / globalConfig usando a sinalização --debug , o detectOpenHandles é a diferença _only_ ...

Se eu executar with --runInBand --detectOpenHandles testes ainda serão bem-sucedidos.

Posso executar usando qualquer um dos seguintes para concluir os testes com sucesso sem mostrar o erro "... não saiu ...":

  • jest --maxWorkers=2
  • jest --detectOpenHandles
  • jest --forceExit

Trabalhando em torno disso com maxWorkers=2 por enquanto, mas essas são minhas observações, apenas para qualquer um que pesquisar no futuro ...

_Editar: Detalhe adicional: isso afeta apenas meu ambiente de CI, que é um contêiner docker FROM alpine: 3.7 executando o nó v8.9.3. Não consigo reproduzir com --maxWorkers=1 na minha máquina dev_

Confirmando que recebo este erro agora. Usar --maxWorkers=10 parece resolver o problema.

Então .... eu estava lutando com isso por um bom tempo (usando travis ci, macacões e datilografados).
Isso acabaria travando e produzindo uma compilação com falha (mas apenas com o Travis CI).

Depois de muita tentativa e erro, descobri que o que consertou isso para mim foi adicionar um caminho explícito para os testes.

Ele falhou com o script npm

   "test": "jest",
    "test:coverage": "npm run test -- --collectCoverage && cat ./src/coverage/lcov.info | coveralls",

E passou (em travis ci) com:

   "test": "jest .*\.test\.ts",
    "test:coverage": "npm run test -- --collectCoverage && cat ./src/coverage/lcov.info | coveralls",

Se você estiver usando o docker com uma imagem UBI do Redhat e create-react-app certifique-se de definir CI=true antes de executar npm test

Dezembro de 2019. Encontrei esse problema SOMENTE no Travis. Os testes passam localmente. A correção de @qopqopqop funcionou para mim. Usando Jest versão 24.9.0

Só encontrei esse erro quando nosso projeto começou a adicionar novos componentes que usam ganchos e biblioteca de teste. Eu acho que pode haver algum atrito entre os ganchos Jest, testing-library e React, já que todas essas são novas tecnologias. Esses projetos ainda estão aprendendo a jogar bem uns com os outros. OU, poderíamos estar escrevendo componentes funcionais realmente problemáticos que usam ganchos incorretamente. :-)

Eu ainda tenho esse problema. Não consigo sair do teste, isso faz com que npm test falhe em todos os meus aplicativos. qualquer pista?

@koooge Você pode postar um exemplo do que não funciona para você?

Para fazer o teste sair com 0 após todos os testes passarem, você deve passar em --watchAll = false
como npm run test - --watchAll = false

isso funcionou para mim

Para fazer isso funcionar com o Firebase, tive que fazer o seguinte:

afterAll(() => {
    firebase.app().delete();
});

Eu corrigi usando a opção:

--forceExit

https://jestjs.io/docs/en/cli# --forceexit

Então, também me deparei com esse problema. Foi irritante ver a mensagem de aviso A worker process has failed to exit gracefully and has been force exited... quando eu sabia que estava lidando com todas as minhas async chamadas corretamente. Fiz meus testes com --detectOpenHandles mas nada apareceu. Depois de alguma pesquisa, descobri que meu culpado era Promise.race .

Eu uso uma biblioteca de utilitário de promessa nativa (https://github.com/blend/promise-utils) e envolvo algumas de minhas chamadas de API externas no utilitário timeout . Este utilitário, por sua vez, usa o Promise.race nativo.

Peguei esse código e criei um caso de teste simples para confirmar minhas descobertas.

it('promise.race', async() => {
  await Promise.race([
    new Promise((res) => setTimeout(res, 10000)),
    Promise.resolve('true')
  ])
})

Assumindo que as configurações de tempo limite do caso de teste são padrão, o teste acima sempre dará o aviso.

Seja qual for a maneira que jest está usando para detectar alças abertas sob o capô, ele não está levando em consideração alças deixadas abertas intencionalmente por Promise.race . Esse caso de uso definitivamente se enquadra na categoria de falso positivo. Não tenho certeza se esse falso-positivo pode ser corrigido, mas talvez um dos desenvolvedores tenha uma solução engenhosa para isso.

Por enquanto, vou ficar com --forceExit como todo mundo.

Editar:
Acabei de encontrar isso, parece que é realmente um problema mais profundo do nodejs / v8 https://github.com/nodejs/node/issues/24321

Para qualquer pessoa que venha aqui dos testes do Firestore, isso funciona para mim:

afterAll(async () => {
  // Shut down Firestore, otherwise jest doesn't exit cleanly
  await firestoreInstance.terminate()
});

Ainda estou tendo o mesmo problema ao usar o Apollo & Jest. Infelizmente, mesmo que a opção --detectOpenHandles eventualmente exista, ela ainda faz o processo pendurar por mais alguns segundos (e em contradição com seu nome: não fornece informações sobre quais identificadores ainda estão abertos!).

Usar --forceExit faz o trabalho, mas imprime irritantemente:

Forçar saída Jest: Você já pensou em usar --detectOpenHandles para detectar operações assíncronas que continuaram em execução após a conclusão de todos os testes?

Uma solução alternativa que encontrei (e isso de forma alguma é uma solução!) É adicionar teardown a jest.config.js:

globalTeardown: '<rootDir>/__tests__/teardown.js',

e em teardown.js use process.exit:

module.exports = async function () {
    console.log('done!');
    process.exit(0);
}

Eu também tenho esse problema. Como posso corrigir isso? Eu defini forceExit: true . --forceExit --detectOpenHandles --maxWorkers=10 não funciona.

https://github.com/atom-ide-community/atom-ide-base/pull/33

Editar: o problema em outro lugar. É no test-runner que estou usando ...

@alusicode
Este não funcionou para mim npm test --watchAll=false
Mas funcionou adicionando --watchAll=false no arquivo package.json. 👍

Gostar

"test": "react-scripts test a jest --ci --reporters=default --reporters=jest-junit --watchAll=false"

Documentos oficiais: https://jestjs.io/docs/en/cli.html# --watchall

Não estou usando o firebase, mas tive o mesmo problema em meus scripts de fluxo de trabalho. usando jest sem parâmetros disse que alguns dos meus scripts não desligaram normalmente e eu deveria usar --runInBand --detectOpenHandles . Isso resolveria o problema de todos os meus testes, exceto um (aliás, --detectOpenHandles não me mostrou os testes que apresentaram problemas).
Então comecei a verificar todos os testes um por um. Descobri que em 2 testes esqueci de usar await quando estava chamando uma função assíncrona.
Depois de adicionar esperar, foi corrigido. Embora eu não ache normal que --detectOpenHandles não imprima as edições.

Esta página foi útil?
0 / 5 - 0 avaliações