Jest est l’un des frameworks de test les plus populaires en JavaScript. Dans cet article, nous allons nous plonger dans l’utilisation correcte de Jest beforeEach pour améliorer les tests unitaires avec JavaScript, allons-y !
Table des matières #
En savoir plus sur Jest #
Jest se présente comme un charmant framework de test JavaScript axé sur la simplicité. Il fonctionne à la fois sur le backend (Node.js) et sur les bibliothèques frontend telles que React, Angular, Vue, etc. Il a également une couverture de moquerie et de code prête à l’emploi. Lancé et maintenu par Facebook, Jest est très utile pour les tests basés sur l’interface utilisateur avec Test instantané.
Plaisanterie avant chaque #
BeforeEach dans Jest fait partie de la montage et démontage traiter. Comme son nom l’indique, si nous voulons exécuter une fonction ou un autre code à plusieurs reprises « avant chaque test », ce code peut être placé dans la fonction beforeEach.
De même, jest a aussi afterEach
fonction qui exécutera un morceau de code chaque fois qu’un test sera terminé, c’est-à-dire démonter. Si nous voulons exécuter du code une seule fois avant l’exécution de tous les tests, Jest a beforeAll
fonction à cet effet.
Si vous vous demandez comment définir plusieurs niveaux de beforeEach et la séquence d’exécution, l’officiel documents faites un excellent travail d’explication. L’exemple de beforeEach
sur les documents officiels avec le chargement de la base de données ne semble pas la chasse pour bien expliquer son utilisation.
Ensuite, nous examinerons un exemple pratique d’obtention des dernières histoires de HackerNews et d’écriture de tests en utilisant jest beforeEach après avoir passé les prérequis.
Conditions préalables #
Pour mieux comprendre l’exemple donné ci-dessous pour ce tutoriel, il serait préférable de connaître les éléments suivants :
- Avoir une connaissance générale du travail de Node.js et NPM sera utile
- Avoir une connaissance de base du fonctionnement de Jest en général et rédiger des tests simples avec Jest
- Connaître le fonctionnement de Github sera utile pour naviguer dans l’exemple de code sur Github
- Une compréhension générale des promesses et de l’attente asynchrone sera bénéfique mais pas obligatoire
Il est temps de jouer avec un peu de code maintenant :).
Exemple de plaisanterie avant chaque #
Pour ce guide, nous utiliserons un exemple d’obtention des dernières histoires de l’API non officielle HackerNews fournie par Algolia. Vous trouverez ci-dessous notre client de nouvelles Hacker qui utilise Axios pour obtenir la dernière histoire sur Hackernews pour un mot-clé donné, si aucun mot-clé n’est fourni, il récupérera toutes les dernières histoires :
Client simple de l’API Hacker News #
module.exports = class HnClient
constructor(axios)
axios.defaults.baseURL = 'https://hn.algolia.com/api/v1';
this.axios = axios;
async getLatestStories(keyword = '')
try catch(e)
console.log(`Error while getting stories $e.message`, e);
return [];
Le client ci-dessus est écrit en tant que classe et exporté pour être utilisé par tout autre fichier qui en a besoin. Il a un constructeur qui s’attend à ce qu’une instance Axios soit transmise. Cela facilite les tests car la dépendance peut être facilement simulée. Dans le constructeur, il définit le baseURL
de l’instance Axios et la définit dans la portée de la classe.
Ensuite, il y a un getLatestStories
méthode qui est asynchrone et prend un paramètre appelé keyword
. Cette méthode fait un get
appel au search_by_date
point de terminaison sur l’API non officielle de hacker news définie comme URL de base dans le constructeur. Il transmet également les paramètres de requête et de balises pour le point de terminaison de l’API, comme indiqué dans leur documents.
Si la response.data
est reçu et il a le hits
propriété qui sera retournée qui est un tableau de magasins d’autre et un tableau vide []
est renvoyé à l’appelant.
De plus, pour rendre la méthode résistante à toute défaillance en appelant l’API Algolia HackerNews (HN) si une erreur se produit, elle atterrira dans le bloc catch et consignera l’erreur, puis renverra un tableau vide. Dans la section suivante, nous verrons comment exécuter la classe ci-dessus pour voir un exemple de sortie.
Exécutez l’exemple de client de l’API Hacker News #
Le code ci-dessus peut être rapidement vu en action en exécutant ce qui suit :
const HnClient = require('./src/hnClient');
const axios = require('axios');const keyword = process.argv[2];
(async () =>
const hnClient = new HnClient(axios);
console.log(`keyword: `, keyword);
const stories = await hnClient.getLatestStories(keyword);
console.table(stories.map(story =>
const title, author = story;
return title, author;
));
)();
Il peut être exécuté avec node index.js javascript
étant donné que le fichier est nommé comme tel et que HnClient
la classe est enregistrée dans le src
dossier. Le index.js utilise un IIFE pour appeler instancier le HnClient
classe avec une instance Axios et enregistre le titre et l’auteur de l’histoire sous la forme d’un tableau dans la console qui ressemble à ce qui suit :
Comme vu le javascript
Le paramètre transmis dans la ligne de commande est transmis jusqu’à l’appel de l’API et les 20 dernières histoires sont extraites de l’API et enregistrées sur la console sous forme de tableau avec le titre et l’auteur de l’histoire.
Tests avec jest beforeEach pour le client HN #
Écrivons quelques tests pour le HnClient
classe que nous avons écrite avec l’utilisation de jest beforeEach qui facilitera le test de la classe. Il existe deux types de tests rapides (unitaires) et non rapides (intégration), nous allons écrire des tests unitaires pour ce guide.
Vous trouverez ci-dessous le cas de test unitaire simple pour le chemin heureux où nous nous attendons à obtenir les dernières histoires pour un mot clé donné :
const HnClient = require('../src/hnClient');
const log = jest.spyOn(console, 'log').mockImplementation(() => );describe('HnClient', () => {
let axiosMock =
defaults: ,
get: jest.fn(),
;
let hnClient;
beforeEach(() =>
hnClient = new HnClient(axiosMock);
);
describe('getLatestStories', () =>
it('should return an array of stories for given keyword', async () =>
const returnedStories = [
created_at: '2022-06-17T13:47:57.000Z',
title: 'Qwik and Partytown: How to remove 99% of JavaScript from main thread',
url: 'https://www.youtube.com/watch?v=0dC11DMR3fU',
author: 'barisx',
,
created_at: '2022-06-17T09:59:00.000Z',
title: 'Prepack – A tool for making JavaScript code run faster',
url: 'https://prepack.io/',
author: 'longrod',
,
];
axiosMock.get = jest.fn().mockResolvedValueOnce( data: hits: returnedStories );
const stories = await hnClient.getLatestStories('javascript');
expect(axiosMock.defaults.baseURL).toBe('https://hn.algolia.com/api/v1');
expect(axiosMock.get).toHaveBeenCalledWith('/search_by_date?query=javascript&tags=story');
expect(stories).toBeInstanceOf(Array);
expect(stories.length).toBe(2);
expect(stories[0]).toHaveProperty('title');
expect(stories[0].title).toBe('Qwik and Partytown: How to remove 99% of JavaScript from main thread');
expect(stories[1]).toHaveProperty('url');
expect(stories[1].url).toBe('https://prepack.io/');
);
);
});
Nous avons écrit un seul test pour le getLatestStories
méthode le chemin heureux pour récupérer les données de l’API HN Algolia. Nous avons instancié le système sous test (SUT) ici comme hnClient
et l’a utilisé plus tard dans le test. Le faire avant chaque ne nous aide pas vraiment jusqu’à présent.
Certaines affirmations comme toBe
sont assez similaires aux assertions PHPUnit si vous les connaissez.
Ajoutons un autre test pour voir le kilométrage que nous obtenons de jest beforeEach :
it('should return an empty array if no stories are found', async () =>
axiosMock.get = jest.fn().mockResolvedValueOnce();const stories = await hnClient.getLatestStories();
expect(stories).toBeInstanceOf(Array);
expect(stories.length).toBe(0);
);
Dans ce test, nous testons le cas où, si aucune donnée n’est renvoyée par l’API, elle doit toujours renvoyer un tableau vide. Maintenant, comme nous pouvons le voir, nous réutilisons le hnClient
défini dans le beforeEach
s’il n’était pas instancié dans le avant chacun, nous aurions besoin de le refaire ici pour ce cas de test.
Image si
hnClient
a 5 dépendances au lieu de 1, ce serait une bonne quantité de configuration et non. de lignes à coder à répéter dans chaque test.
C’est ici que beforeEach
brille s’il est nécessaire d’exécuter certaines lignes de code avant chaque exécution de test, il peut être placé dans la section beforeEach et terminé.
Nous pouvons ajouter un autre cas de test pour tester le scénario lorsque l’API génère une erreur et que l’exécution atterrit dans la partie catch du code comme suit :
it('should handle any error and return empty stories array', async () =>
axiosMock.get = jest.fn().mockRejectedValueOnce(new Error('server down'));const stories = await hnClient.getLatestStories('python');
expect(log).toHaveBeenCalledWith(expect.stringContaining('server down'), expect.anything());
expect(stories).toBeInstanceOf(Array);
expect(stories.length).toBe(0);
);
Même ici, nous utilisons commodément le hnClient
instancié correctement dans le beforeEach qui a la dépendance nécessaire de l’instance Axios. Nous ajustons les axiosMock’s get
méthode pour lancer une erreur comme un rejet de promesse et qui fait le travail. C’est la puissance et la facilité d’utilisation de beforeEach qui rendent la rédaction de tests bien meilleure et plus facile.
Avec les 3 tests ci-dessus, nous aurons une couverture de code à 100 % qui peut être vue en exécutant :
npm run test:cov
Le commun ci-dessus est mappé sur jest –coverage
et comme jest a une couverture de code intégrée, il donne la sortie suivante :
Vous pouvez trouver le code complet de ce projet dans ce Référentiel GitHub et les parties les plus importantes de l’exemple dans ce demande d’extraction.
Conclusion #
Nous avons appris à utiliser jest BeforeEach dans ce didacticiel pour améliorer et faciliter l’écriture des tests JavaScipt avec des réutilisations optimales du code dans les tests.
J’espère que cela vous aidera à écrire des tests encore meilleurs avec JavaSciprt, que ce soit pour Node.js (Backend) ou d’autres frameworks/bibliothèques frontend comme React, Vue ou tout autre.
Continuez à écrire des tests pour éviter les maux de tête :).