Projet numérologie : partie 5 / tests unitaires : base de données
Tester les appels en base ne peut se faire avec la base de production ou de développement. Deux solution sont possible pour effectuer les tests :
- avoir une base de test qui sera réinitialisée entre chaque test pour isoler les testes des uns des autres.
- on simule une base de donnée (mock)
Environnement de test
Créons une base de donnée en mémoire pour notre environnement de tests.
Dans le fichier db.js
, on remplace la création de la constante sequelize par :
// ...
let env = process.env.NODE_ENV || "development";
let storage;
if (env === "test") {
storage = ":memory:";
} else {
storage = path.join(__dirname, "db.sqlite");
}
const sequelize = new Sequelize({
dialect: "sqlite",
storage: storage,
logging: (msg) => logger.info(msg),
});
// ...
Tests
On peut maintenant créer nos tests.
- avant tous les tests : crée une base
- avant chaque test : on vide la base des données testées et on crée ce dont on a besoin dans chaque test
- utilisation de supertest pour tester l'accès à la base via les routes
Fichier __tests__/db.js
:
import request from "supertest";
import { app } from "../app.js";
import db from "../db.js";
let user;
let server;
beforeAll(async () => {
user = await request.agent(app);
server = await app.listen(3001); // test en parallèle et parfois 3000 et 3001
await db.sequelize.sync({ force: true });
});
afterAll(async () => {
await server.close();
});
describe("prénoms", () => {
beforeEach(async () => {
await db.model.Prénoms.sync({ force: true });
await db.model.Signification.sync({ force: true });
});
test("Prénom read", async () => {
await db.model.Prénoms.create({
prénom: "Carole",
});
await db.model.Signification.create({
message: "Quatre",
nombre: 4,
});
await user
.get(encodeURI("/prénom?valeur=Carole"))
.expect(200)
.expect("Content-Type", /json/)
.expect(function (res) {
expect(res.body).toEqual({
chiffre: 4,
message: "Quatre",
prénom: "Carole",
});
});
});
});
Quelques subtilités :
- on a changé le port du serveur en 3001. Comme les tests s'effectuent en parallèle, il est parfois possible que les 2 tests supertests soient exécutées ensembles
- nos tests sont passés en asynchrones
- on test le résultat de la requête. C'est à priori inutile si on ne teste que la route. Comme ici, le test fait office de test de route et de fonctionnalité, on le laisse.