Testing Utilities
createTestApp() — Alles in einem Aufruf
const app = await createTestApp({ features: [orderFeature, clientFeature],});
afterAll(() => app.cleanup());Erstellt: echte PostgreSQL (frische DB), echte Redis (eigener DB-Index), Feature Registry, Pipeline — alles real, keine Mocks.
Testen ohne HTTP
// Write direkt aufrufen:const result = await app.write("order.create", { payload: { clientId: 1, state: "new" }, as: { userId: 1, tenantId: 1, roles: ["Admin"] },});expect(result.isSuccess).toBe(true);
// Query direkt aufrufen:const orders = await app.query("order.list", { payload: { limit: 50 }, as: { userId: 1, tenantId: 1, roles: ["Admin"] },});expect(orders.items).toHaveLength(1);Entity Factories
Auto-generiert aus Schema. Nur angeben was fuer den Test relevant ist — Rest wird mit sinnvollen Defaults gefuellt.
// Manuell (ohne Factory — muehsam):await db.insert(orders).values({ tenantId: 1, clientId: 1, state: "new", priority: 0, currency: "EUR", insertedById: 1, insertedAt: new Date(), isDeleted: false, version: 1,});
// Mit Factory — nur was relevant ist:const order = await app.create("order", { clientId: 1 });// state=new, priority=0, currency=EUR, tenantId aus Context, etc.
// Mehrere auf einmal:const orders = await app.createMany("order", { clientId: 1 }, { count: 50 });Wie Defaults funktionieren
| Feld-Typ | Factory-Default |
|---|---|
text (required) | "test_{fieldName}_{counter}" |
text (optional) | null |
number | default aus Schema oder 0 |
boolean | default aus Schema oder false |
select | Erste Option |
date | new Date() |
| Relations (foreignKey) | Muss angegeben werden oder auto-create |
Auto-Create Relations
// Order braucht Client — Factory erstellt automatisch einen:const order = await app.create("order");// → Client wird automatisch erstellt, clientId gesetzt
// Oder explizit:const client = await app.create("client", { name: "ACME" });const order = await app.create("order", { clientId: client.id });Test-Helpers
// User simulieren:const admin = app.asUser({ id: 1, tenantId: 1, roles: ["Admin"] });const driver = app.asUser({ id: 2, tenantId: 1, roles: ["Driver"] });
// Access testen:await expect(app.write("order.create", { payload, as: driver })) .rejects.toThrow(AccessDeniedError);
// Events pruefen:const events = app.getEmittedEvents();expect(events).toContainEqual({ type: "orders.order.created", payload: { ... } });
// Jobs pruefen:const jobs = app.getEnqueuedJobs();expect(jobs).toContainEqual({ name: "orders.sendNotification", payload: { ... } });Full-Stack Integration Test
// Mit HTTP (Hono Test Client):const response = await app.client.write.$post({ json: { type: "order.create", payload: { clientId: 1 }, requestId: "test-1" },}, { headers: admin.authHeader() });
expect(response.status).toBe(200);expect((await response.json()).isSuccess).toBe(true);