Tester les applications Encore.ts
Instructions
Encore.ts utilise les outils TypeScript standard pour les tests. La configuration recommandée est Vitest.
Configurer Vitest
npm install -D vitest
Ajoutez à package.json :
{
"scripts": {
"test": "vitest"
}
}
Tester un endpoint API
// api.test.ts
import { describe, it, expect } from "vitest";
import { hello } from "./api";
describe("hello endpoint", () => {
it("returns a greeting", async () => {
const response = await hello();
expect(response.message).toBe("Hello, World!");
});
});
Exécuter les tests
# Exécuter avec Encore (recommandé - configure l'infrastructure)
encore test
# Ou exécuter directement avec npm
npm test
L'utilisation de encore test est recommandée car elle :
- Configure automatiquement les bases de données de test
- Fournit une infrastructure isolée par test
- Gère les dépendances de services
Tester avec des paramètres de requête
// api.test.ts
import { describe, it, expect } from "vitest";
import { getUser } from "./api";
describe("getUser endpoint", () => {
it("returns the user by ID", async () => {
const user = await getUser({ id: "123" });
expect(user.id).toBe("123");
expect(user.name).toBeDefined();
});
});
Tester les opérations de base de données
Encore fournit des bases de données de test isolées :
// user.test.ts
import { describe, it, expect, beforeEach } from "vitest";
import { createUser, getUser, db } from "./user";
describe("user operations", () => {
beforeEach(async () => {
// Nettoyer avant chaque test
await db.exec`DELETE FROM users`;
});
it("creates and retrieves a user", async () => {
const created = await createUser({ email: "test@example.com", name: "Test" });
const retrieved = await getUser({ id: created.id });
expect(retrieved.email).toBe("test@example.com");
});
});
Tester les appels entre services
// order.test.ts
import { describe, it, expect } from "vitest";
import { createOrder } from "./order";
describe("order service", () => {
it("creates an order and notifies user service", async () => {
// Les appels de service fonctionnent normalement dans les tests
const order = await createOrder({
userId: "user-123",
items: [{ productId: "prod-1", quantity: 2 }],
});
expect(order.id).toBeDefined();
expect(order.status).toBe("pending");
});
});
Tester les cas d'erreur
import { describe, it, expect } from "vitest";
import { getUser } from "./api";
import { APIError } from "encore.dev/api";
describe("error handling", () => {
it("throws NotFound for missing user", async () => {
await expect(getUser({ id: "nonexistent" }))
.rejects
.toThrow("user not found");
});
it("throws with correct error code", async () => {
try {
await getUser({ id: "nonexistent" });
} catch (error) {
expect(error).toBeInstanceOf(APIError);
expect((error as APIError).code).toBe("not_found");
}
});
});
Tester le Pub/Sub
// notifications.test.ts
import { describe, it, expect, vi } from "vitest";
import { orderCreated } from "./events";
describe("pub/sub", () => {
it("publishes order created event", async () => {
const messageId = await orderCreated.publish({
orderId: "order-123",
userId: "user-456",
total: 9999,
});
expect(messageId).toBeDefined();
});
});
Tester les tâches Cron
Testez la fonction sous-jacente, pas l'horaire cron :
// cleanup.test.ts
import { describe, it, expect } from "vitest";
import { cleanupExpiredSessions } from "./cleanup";
describe("cleanup job", () => {
it("removes expired sessions", async () => {
// Créer d'abord quelques sessions expirées
await createExpiredSession();
// Appeler l'endpoint directement
await cleanupExpiredSessions();
// Vérifier que le nettoyage s'est produit
const remaining = await countSessions();
expect(remaining).toBe(0);
});
});
Mocker les services externes
import { describe, it, expect, vi, beforeEach } from "vitest";
import { sendWelcomeEmail } from "./email";
// Mocker l'API externe
vi.mock("./external-email-client", () => ({
send: vi.fn().mockResolvedValue({ success: true }),
}));
describe("email service", () => {
it("sends welcome email", async () => {
const result = await sendWelcomeEmail({ userId: "123" });
expect(result.sent).toBe(true);
});
});
Configuration des tests
Créez vite.config.ts (requis pour les imports ~encore) :
/// <reference types="vitest" />
import { defineConfig } from "vite";
import path from "path";
export default defineConfig({
resolve: {
alias: {
"~encore": path.resolve(__dirname, "./encore.gen"),
},
},
test: {
globals: true,
environment: "node",
include: ["**/*.test.ts"],
coverage: {
reporter: ["text", "json", "html"],
},
},
});
Intégration VS Code
Installez l'extension Vitest et ajoutez à .vscode/settings.json :
{
"vitest.commandLine": "encore test"
}
Remarque : Pour l'explorateur de tests VS Code, désactivez le parallélisme au niveau des fichiers pour éviter les conflits de ports :
// vite.config.ts
export default defineConfig({
// ...
test: {
fileParallelism: false, // Désactiver pour VS Code
// ...
},
});
Réactivez pour CI : encore test --fileParallelism=true
Directives
- Utilisez
encore testpour exécuter les tests avec la configuration de l'infrastructure - Chaque fichier de test reçoit une transaction de base de données isolée (annulée après)
- Testez les endpoints API en les appelant directement comme des fonctions
- Les appels entre services fonctionnent normalement dans les tests
- Mockez les dépendances externes (APIs tiers, services d'email, etc.)
- Ne mockez pas l'infrastructure Encore (bases de données, Pub/Sub) - utilisez la vraie chose