Jest: Le processus Jest ne se ferme pas après la fin du dernier test

Créé le 18 août 2016  ·  60Commentaires  ·  Source: facebook/jest

J'ai des problèmes avec le processus Jest qui ne se termine pas une fois le dernier test terminé. L'utilisateur devra forcer la fermeture du processus avec ctrl-c. Ma théorie est que toutes les ressources ne sont pas nettoyées de manière appropriée par les auteurs du test, mais idéalement, Jest devrait quand même quitter.

Plus précisément, je teste Firebase avec firebase-server , en faisant tourner un ou plusieurs serveurs pour chaque test. Dans une action afterEach , nous appelons la méthode close pour tous les serveurs créés lors du dernier test, mais même avec cette méthode, le processus Jest ne se ferme toujours pas.

Existe-t-il un moyen de forcer le processus Jest à se fermer une fois les tests terminés (réussite ou échec)? Existe-t-il un moyen d'obtenir un hook afterAll pour nettoyer toutes les ressources restantes? Existe-t-il un moyen de déboguer ce qui empêche exactement le processus Jest de s'arrêter? Merci.

Enhancement Help Wanted good first issue

Commentaire le plus utile

pour toute personne lisant, vous pouvez utiliser le drapeau --forceExit pour accéder à cette fonctionnalité. 🎉

Tous les 60 commentaires

Nous n'avons pas de bon moyen de le faire pour le moment. Je recommanderais d'essayer de connecter un débogueur (Chrome Inspector) pour comprendre ce qui se passe. Si vous savez ce qui crée le travail asynchrone, vous pouvez potentiellement le patcher et le suivre (comme mettre quelque chose autour de Promise.prototype.then)

Y a-t-il une raison pour laquelle le travail asynchrone ne peut pas être forcé à quitter lorsque tous les hooks afterEach / after sont résolus?

Je ne sais pas comment vous tueriez les processus asynchrones existants si vous ne les maîtrisez pas.

J'ai migré de ava et ce n'était pas un problème, alors peut-être y a-t-il une réponse? Peut-être que c'est process.exit dans Node.js

Nous pourrions le faire, je suppose, mais je crains que cela ne laisse les gens suspendus quand il le devrait et qu'ils ne coupent pas correctement leurs ressources.

cc @dmitriiabramov qu'en pensez-vous?

Un exemple: j'en ai rencontré moi-même avec Jest, où nous avions un long processus d'observation qui ne mettrait pas fin à Jest lui-même. Si Jest s'était tué pendant le test (hé!), Je n'aurais jamais remarqué le problème et j'aurais expédié une version qui se bloquerait lorsque les gens essaient de l'utiliser.

je ne suis pas sûr qu'il soit sûr de forcer le processus à tuer. en même temps, si les gens veulent faire un post-traitement asynchrone après la fin des tests, ils peuvent utiliser after all hook qui attendra la fin avant de quitter le processus.

L'autre problème que nous pourrions avoir est de couper le flux de sortie avant la fin de l'impression. nous avons déjà eu ce problème, lorsque les messages d'erreur n'ont pas assez de temps pour s'imprimer avant la fin du processus.

La question est de savoir si nous pourrions trouver un moyen pour Jest de dire "On dirait que certains tests ne se nettoient pas après eux-mêmes. Voici ce qui se passe".

Un hook after all pourrait m'aider ici, mais je n'ai pas vu une telle chose dans la documentation (seulement afterEach ) est-ce que je manque quelque chose?

Quant au test des nettoyages corrects, si vous pouviez tester si les _files_ se terminaient à temps et s'ils n'utilisaient pas une fonction de bissectrice pour isoler le problème (comme dans rspec).

Ok, donc après plus de recherches, cela semble être un problème avec Firebase lui-même, et il n'y a aucun moyen de nettoyer sans appeler process.exit .

Ressources:

Toutes les solutions de contournement impliquent d'appeler manuellement process.exit . J'ai peur de faire cela dans un contexte Jest, y a-t-il une recommandation sur l'endroit où placer un tel appel? Ma première pensée a été quelque chose comme:

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

… Pour quitter une seconde après la fin de tous les tests pour laisser Jest faire son travail, mais je ne sais pas comment cela affecte le mode montre, et si j'ai raison, Jest fait des trucs fantaisistes de parallélisme qui pourraient faire en sorte que cela ne fonctionne pas comme prévu. Sinon, est-ce que c'est quelque chose que vous devez corriger dans Jest proprement dit? Si cela semble être une arme à feu pour un certain nombre de personnes, pourquoi ne pas la mettre dans Jest? Ou au moins un basculement entre le mode «avertir» et le mode «tuer».

J'adorerais un drapeau --exit ou quelque chose (cela pourrait être un commentaire par fichier ou quelque chose) qui ferme automatiquement les processus lorsque les tests sont terminés, similaire à mocha. c'est un peu ennuyeux de fermer manuellement chaque connexion dans chaque fichier de test.

J'ai le même problème lorsque j'exécute des tests dans Codeship . Il échoue également
Localement, cela fonctionne correctement.

ÉDITER:

  • Version blague: 15.1.1
  • Local :

    • Nœud: 6.2.2

    • npm: 3.9.5

  • CodeShip :

    • Nœud: 6.5.0

    • npm: 3.10.3

  • Drone.io

    • Nœud: 0.10.26

    • npm: 1.4.3

Il me semble que Firebase devrait être corrigé.

Je n'ai aucune réserve contre l'ajout d'une option appelée --forceExitAfterTestRun et cela devrait être facile à ajouter. Je pense que cela nécessite juste un changement pour quitter ici: https://github.com/facebook/jest/blob/master/packages/jest-cli/src/cli/index.js#L41 si le drapeau est donné quel que soit le résultat.

Semble être une sorte de condition de course. Parfois, il se ferme après avoir exécuté tous les tests localement, parfois non ...

J'exécute cela aussi après avoir commencé à utiliser Jest pour mes spécifications d'API où j'utilise une base de données réelle au lieu de simulations (désolé 😇 mais les instantanés sont parfaits pour cela). J'ai encore pu résoudre le problème même après avoir ajouté des hooks afterAll pour nettoyer les connexions, ce qui me porte à croire que c'est en quelque sorte lié à ma population d'appareils dans setupFiles , ce n'est pas le plus facile à déboguer.

Jasmine semble avoir l'option --forceexit , donc je ne me plaindrais pas si une chose similaire atterrissait également sur Jest 🙏

un autre problème - si un test échoue, alors afterAll() n'est pas appelé, donc rien n'est nettoyé et rien ne se ferme. je pense que --bail va résoudre ce problème mais je n'ai pas encore essayé

Si quelqu'un souhaite envoyer un PR, c'est quelque chose pour lequel nous pourrions utiliser un peu d'aide et j'ai décrit les détails dans mon commentaire précédent :)

Je vais essayer si j'ai du temps pendant le week-end. Si quelqu'un veut le faire avant cela, ce serait cool: souriez:

Clôture au profit du PR qui vient de s'ouvrir. Nous poursuivrons la discussion là-bas.

pour toute personne lisant, vous pouvez utiliser le drapeau --forceExit pour accéder à cette fonctionnalité. 🎉

Pour les googleurs: Jest ne se ferme pas sur Jenkins CI, alors qu'il le fait localement .. --forceExit effectivement corrigé pour moi.

Pour moi, c'était oublier de gérer la promesse avec .then (() => {}) - a fait le travail

J'ai encore du mal avec ça. Je teste une API avec async et await . Je me connecte à mon application express et envoie un ping à un point de terminaison, mais le test ne se ferme pas. J'ai essayé de fermer la connexion à mongodb et au serveur mais elle est toujours ouverte. Je ne renvoie que des json vides.

Dans mon cas, cela a fini par être un problème Firebase. En utilisant

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

semble faire l'affaire. J'ai trouvé que les deux lignes sont réellement nécessaires et que vous devez utiliser le même firebaseApp que vous obtenez à l'origine de .initializeApp() .

Existe-t-il un moyen de résoudre ce problème sans forcer?

Jest 23 inclut un indicateur appelé --detectOpenHandles qui devrait indiquer la raison pour laquelle Jest est incapable de quitter

--detectOpenHandles renvoie mongoose.connect et mongoose.model. Essayer de mongoose.disconnect dans afterAll soulève une erreur de mongo Topologie détruite.

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

@elkhan avez-vous trouvé comment résoudre les problèmes de mangouste?

Après avoir ajouté --detectOpenHandles , non seulement Jest termine mes tests et ne montre rien qui bloque réellement Jest, ce qui est bizarre. On dirait un bug.

Pour moi, --forceExit résout le problème, en même temps j'utilise --detectOpenHandles mais il ne détecte rien (à la fois localement et sur CircleCI). Je cours aussi avec --runInBand .

Pour moi, supprimer --runInBand résolu.

--forceExit résout le problème pour moi aussi lors de l'utilisation de shippable ... J'ai essayé --detectOpenHandles mais n'a donné aucun résultat et a tout de même provoqué le blocage de la compilation

L'ajout de --detectOpenHandles résout le problème, ce qui est bizarre.

Nœud: v8.12.0
Blague: v23.6.0

L'ajout de --detectOpenHandles ou --forceExit ne résout pas le problème pour moi lors de l'exécution sur Codeship.

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

Nœud: v8.12.0
Blague: v23.6.0

@sibelius un moyen d'éviter ce problème est de désactiver la fonction init du modèle

const mongoose = require('mongoose');

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

Cela empêchera Jest de se plaindre des modèles, bien que les index ne soient pas créés

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 les tests sont réussis, mais le code dans .then ou .catch ne fonctionne pas !!
des idées?

@alexpchin Voici comment je l'ai résolu:

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

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

Avec NestJs, je devais ajouter

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

Nous avons constaté que ce problème était dû au fait que le processus de plaisanterie manquait de mémoire. L'ajout de --maxWorkers=10 résolu le problème pour nous.

J'ajoute cette cause, peut-être que quelqu'un qui se demande dans ce problème pourrait en avoir la raison comme moi.
J'utilisais Jest dans Travis pour tester une application NodeJS et travis est resté suspendu jusqu'à expiration du délai juste après Jest. Apparaît Jest ne fermait pas.
Après de nombreux essais, j'ai découvert que la raison était d'utiliser jest avec JSDom.
J'avais la ligne suivante dans mon fichier jest.config.js :

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

Ce qui a provoqué le chargement de JSDom et supposé ne pas fermer toutes les ressources correctement et garder Jest en vie.

Je l'ai résolu en supprimant la ligne - cependant Jest échouera alors avec l'erreur suivante voir ceci :

SecurityError: localStorage is not available for opaque origins

Pour le résoudre, j'ai ajouté ce qui suit à jest.config.js :

  'testEnvironment': 'node',

J'espère que cela aide tout le monde. J'ajoute cette cause, peut-être que quelqu'un qui se demande dans ce problème pourrait en avoir la raison comme moi.
J'utilisais Jest dans Travis pour tester une application NodeJS et travis est resté suspendu jusqu'à expiration du délai juste après Jest. Apparaît Jest ne fermait pas.
Après de nombreux essais, j'ai découvert que la raison était d'utiliser jest avec JSDom.
J'avais la ligne suivante dans mon fichier jest.config.js :

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

Ce qui a provoqué le chargement de JSDom et supposé ne pas fermer toutes les ressources correctement et garder Jest en vie.

Je l'ai résolu en supprimant la ligne - cependant Jest échouera alors avec l'erreur suivante voir ceci :

SecurityError: localStorage is not available for opaque origins

Pour le résoudre, j'ai ajouté ce qui suit à jest.config.js :

  'testEnvironment': 'node',

J'espère que cela aide n'importe qui.

--forceExit --detectOpenHandles --maxWorkers = 10

l'a fait pour nous

nœud: 8.11.3
plaisanterie 23.6.0

Avec NestJs, je devais ajouter

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

Laissez simplement ceci ici pour les personnes NestJS:
Avec NestJS, j'ai découvert que la réponse ci-dessus fonctionne.
Ce qui ne fonctionne pas est le suivant:

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

pour moi, c'est --forceExit --maxWorkers=10 qui fonctionne (je suis sur Ubuntu 18.04, en utilisant [email protected])

Dans mon cas, l'utilisation de NodeJS 10 ou 11 résout le problème, mais il est toujours là avec Node 6 ou Node 8. rien ne s'affiche lorsque vous utilisez l'option --detectOpenHandles , et --forceExit corrige également le problème.

+1 personne de plus ici (comme @motss et @seanlindo ) observant que le _ "Jest ne s'est pas terminé une seconde après la fin du test." _ Se produit uniquement lorsque --detectOpenHandles n'est pas utilisé.

[email protected]

Les tests échouent systématiquement sans --detectOpenHandles mais réussissent et ne montrent aucun handle ouvert lorsqu'ils sont exécutés avec --detectOpenHandles .

La machine / conteneur exécutant les tests a deux cœurs, mais par défaut, les tests sont exécutés avec maxWorkers=1

Quand j'ajoute le drapeau --detectOpenHandles et que je regarde la configuration / globalConfig en utilisant le drapeau --debug , la detectOpenHandles est la différence _only_ ...

Si j'exécute les tests with --runInBand --detectOpenHandles , ils réussissent toujours.

Je peux utiliser l'un des éléments suivants pour terminer les tests avec succès sans afficher l'erreur "... n'a pas quitté ...":

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

Travailler autour de ça avec maxWorkers=2 pour l'instant, mais ce sont mes observations, juste pour tous ceux qui cherchent dans le futur ...

_Edit: Détail supplémentaire: cela n'affecte que mon environnement CI, qui est un conteneur docker FROM alpine: 3.7 exécutant le nœud v8.9.3. Je ne peux pas reproduire avec --maxWorkers=1 sur ma machine de développement_

Confirmant que j'obtiens cette erreur maintenant. L'utilisation de --maxWorkers=10 semble résoudre le problème.

Donc ... Je me suis battu avec ça pendant un certain temps (en utilisant travis ci, une combinaison et un manuscrit).
Cela finirait par se bloquer et produire une compilation échouée (mais uniquement avec Travis CI).

Après de nombreux essais et erreurs, j'ai trouvé ce qui a résolu ce problème pour moi, c'est que j'ai ajouté un chemin explicite aux tests.

Il a échoué avec le script npm

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

Et passé (en travis ci) avec:

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

Si vous utilisez docker avec une image UBI Redhat et create-react-app assurez-vous de définir CI=true avant d'exécuter npm test

Décembre 2019. Ran dans ce numéro UNIQUEMENT sur Travis. Les tests passent localement. Le correctif de

Je n'ai rencontré cette erreur que lorsque notre projet a commencé à ajouter de nouveaux composants utilisant des hooks et testing-library. Je pense qu'il peut y avoir des frictions entre Jest, testing-library et React hooks car ce sont toutes de nouvelles technologies. Ces projets apprennent encore à bien jouer les uns avec les autres. OU, nous pourrions écrire des composants fonctionnels vraiment bogués qui n'utilisent pas correctement les hooks. :-)

J'ai toujours ce problème. Je ne peux pas quitter le test, cela fait échouer npm test pour toutes mes applications. un indice?

@koooge Pouvez-vous publier un exemple de ce qui ne fonctionne pas pour vous?

Pour que le test se termine avec 0 après la réussite de tous les tests, vous devez passer --watchAll = false
comme npm run test - --watchAll = false

cela a fonctionné pour moi

Pour que cela fonctionne avec Firebase, je devais faire ceci:

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

Je l'ai corrigé en utilisant l'option:

--forceExit

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

J'ai donc rencontré ce problème également. C'était ennuyeux de voir le message d'avertissement A worker process has failed to exit gracefully and has been force exited... quand je savais que je gérais correctement tous mes appels async . J'ai effectué mes tests avec le --detectOpenHandles mais rien ne s'est affiché. Après quelques recherches, j'ai découvert que mon coupable était Promise.race .

J'utilise une bibliothèque d'utilitaires de promesse native (https://github.com/blend/promise-utils) et j'emballe certains de mes appels d'API externes dans l'utilitaire timeout . Cet utilitaire utilise à son tour le natif Promise.race .

J'ai sorti ce code et créé un cas de test simple pour confirmer mes résultats.

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

En supposant que les paramètres de délai d'expiration de votre scénario de test sont par défaut, le test ci-dessus donnera toujours l'avertissement.

Quelle que soit la manière dont jest utilise pour détecter les poignées ouvertes sous le capot, il ne prend pas en compte les poignées laissées intentionnellement ouvertes par Promise.race . Ce cas d'utilisation relève définitivement de la catégorie des faux positifs. Je ne suis pas sûr que ce faux positif soit réparable, mais peut-être que l'un des développeurs a une solution ingénieuse à ce problème.

Pour l'instant, je m'en tiens à --forceExit comme tout le monde.

Éditer:
Je viens de trouver ceci, il semble que ce soit en effet un problème plus profond de nodejs / v8 https://github.com/nodejs/node/issues/24321

Pour toute personne venant ici des tests Firestore, cela fonctionne pour moi:

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

J'ai toujours le même problème avec Apollo & Jest. Malheureusement, même si l'option --detectOpenHandles finit par se terminer, elle suspend encore le processus pendant quelques secondes (et en contradiction avec son nom: elle ne fournit pas d'informations sur les poignées encore ouvertes!).

L'utilisation de --forceExit fait le travail mais affiche de manière ennuyeuse:

Forcer la sortie de Jest: Avez-vous envisagé d'utiliser --detectOpenHandles pour détecter les opérations asynchrones qui s'exécutaient après> tous les tests terminés?

Une solution de contournement que j'ai trouvée (et ce n'est en aucun cas une solution!) Est d'ajouter un teardown à jest.config.js:

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

et dans teardown.js, utilisez process.exit:

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

J'ai aussi ce problème. Comment puis-je y remédier? J'ai mis forceExit: true . --forceExit --detectOpenHandles --maxWorkers=10 ne fonctionne pas.

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

Edit: le problème ailleurs. C'est dans le test-runner que j'utilise ...

@alusicode
Celui-ci n'a pas fonctionné pour moi npm test --watchAll=false
Mais cela a fonctionné en ajoutant --watchAll=false dans le fichier package.json. 👍

Comme

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

Documents officiels: https://jestjs.io/docs/en/cli.html# --watchall

Je n'utilise pas Firebase mais j'ai eu le même problème sur mes scripts de workflow. l'utilisation de jest sans paramètres a dit que certains de mes scripts ne s'étaient pas arrêtés correctement et que je devrais utiliser --runInBand --detectOpenHandles . Cela résoudrait le problème pour tous mes tests sauf un (btw --detectOpenHandles ne m'a pas montré les tests qui avaient des problèmes).
J'ai donc commencé à vérifier tous les tests un par un. J'ai découvert que pour 2 tests, j'ai oublié d'utiliser await lorsque j'appelais une fonction asynchrone.
Après avoir ajouté wait, il a été corrigé. Bien que je ne pense pas qu'il soit normal que --detectOpenHandles n'imprime pas les problèmes.

Cette page vous a été utile?
0 / 5 - 0 notes