Test avec Jest

Tags :
  • MON
  • 2023-2024
  • temps 3
  • javascript
  • jest
  • Express
Auteurs :
  • Lucas Rioual

Test

Javascript

Introduction

L’objectif de ce MON est de me former sur les tests javascript. Je souhaite me concentrer sur cette thématique car c’est quelque chose qui est primordial pour faire du code professionnel.

Je vais m’attarder sur la biblothèque Jest qui permet de tester du code Javascript. Je vais utiliser le backend du projet Killer pour m’entrainer.

Tester du code Javascript

Je voulais savoir comment tester l’API du projet Killer car pour l’instant, pour tester les différentes fonctionnalités, j’utilise l’interface de l’application. C’est long à tester une fonctionnalité mais surtout, il est difficile de tester une seule fonctionnalité à la fois. L’objectif est donc de pouvoir tester les différentes routes de l’API et s’assurer que le résultat renvoyé est bien celui attendu.

J’ai utilisé ces deux tuto :

Cela permet de tester une application Express qui communique avec une base de donnée Mongo DB.

Voici comment installer les dépendances nécessaire :

npm install --save-dev jest supertest 
npm install mongoose

Ensuite, le but est de tester mon application sans tout casser. En effet, les tests permettront d’intéragir avec la base de donnée. Cependant, lorsqu’on effectue des tests, il ne faut pas modifier la vrai base de donnée qui est utilisé par l’application en production. Pour cela, on crée un ficher .env qui stocke des variables d’environnement :

MONGODB_URI='url'
MONGODB_URI_TEST='url de test'

Comme ça on peut choisir quel url choisir n’importe où dans l’application

Ensuite on rajoute un script dans package.json :

"scripts": {
    "test": "jest"
  },

Tester une route

Maintenant, je souhaite tester la route POST /api/user/testUser qui permet d’ajouter un nouvel utilisateur dans la base de donnée avec le nom ‘testUser’.

Voici le code que j’ai qui permet de tester cette route :


describe("User API", () => {
  beforeAll(async () => {
    await mongoose.connect(process.env.MONGODB_URI_TEST);
  });

  afterAll(async () => {
    await mongoose.connection.close();
  });

  beforeEach(async () => {
    await User.deleteMany({})
    await Game.deleteMany({});
  });
  describe("POST /user", () => {
    it("doit créer un nouvel utilisateur", async () => {
      const response = await request(app)
        .post("/api/user/testUser")
        .send({ expoToken: "testToken" });
      expect(response.statusCode).toBe(200);
      expect(response.body).toHaveProperty("success", true);
      expect(response.body).toHaveProperty("userId");
    });
  });
});

Le code commence par définir une suite de tests avec describe("User API", () => { ... }). Cette suite de tests contient plusieurs hooks et blocs de tests.

Maintenant si on fait npm run test on a ce resultat :

PS D:\Programmation\Ecm\Killer-back> npm run test

> killer-back@1.0.0 test
> jest

 PASS  test/user.test.js
  User API
    POST /user
      √ doit créer un nouvel utilisateur (280 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.952 s, estimated 8 s
Ran all test suites.

Tester la modification d’un utilisateur

Ensuite, je souhaite tester la route PUT /api/user/ qui permet de modifier le surnom d’un utilisateur. Le problème, c’est qu’au début des tests, ma base de donnée est vide. J’ai donc crée 3 utilisateurs de test que j’évite de supprimer à la fin des test :


const user1Id = "65fd4cbe4352edb5a9722609";
const user2Id = "65fd4cdb034e02d9b0920de8";
const user3Id = "65fd511875033da71380cc99";

describe("User API", () => {
  beforeAll(async () => {
    await mongoose.connect(process.env.MONGODB_URI_TEST);
  });

  afterAll(async () => {
    await mongoose.connection.close();
  });

  beforeEach(async () => {
    await User.deleteMany({
      _id: {
        $nin: [
          user1Id,
          user2Id,
          user3Id,
          
        ],
      },
    })
    await Game.deleteMany({});

  });

  describe("POST /user", () => {
    it("doit créer un nouvel utilisateur", async () => {
      const response = await request(app)
        .post("/api/user/testUser")
        .send({ expoToken: "testToken" });
      expect(response.statusCode).toBe(200);
      expect(response.body).toHaveProperty("success", true);
      expect(response.body).toHaveProperty("userId");
    });
    it("modifier le surnom de l'utilisateur", async () => {
      const response = await request(app)
        .put(`/api/user/${user1Id}`)
        .send({ expoToken: "testToken", userName: "Tom" });
      expect(response.statusCode).toBe(200);
      expect(response.body).toHaveProperty("success", true);
      expect(response.body).toHaveProperty("userId");
    });
    it("modifie le surnom de l'utilisateur mais l'id n'existe pas dans la base de donnée", async () => {
      const response = await request(app)
        .put("/api/user/65f58e6326c2f024807a6376")
        .send({ expoToken: "testToken", userName: "Tom" });
      expect(response.statusCode).toBe(200);
      expect(response.body).toHaveProperty("success", true);
      expect(response.body).toHaveProperty("userId");
    });
  });
});

Conclusion

Il y a pleins d’autres routes à tester pour s’assurer que l’application fonctionne bien. Cependant je n’ai pas eu le temps de toutes les tester. J’ai mis pas mal de temps à faire fonctionner le premier test car j’avais des soucis pour me connecter à la base de donnée. Je n’ai pas eu le temps de passer les 10h sur ce MON. J’ai passé environ 6h sur la documentation et les exemples que j’ai présenté.