Node.js Test Tipps - REST API mit CORS
Im dritten Beitrag zu Node.js-Testtipps stelle ich meinen Ansatz zur Prüfung der REST-Schnittstelle vor. Wie gewohnt gibt es Hands-on-Codebeispiele und die Liste der notwendigen NPM-Pakete, damit du das in wenigen Minuten bei dir zum Laufen bringst. Legen wir mit dem heutigen Schwerpunkt auf CORS los.
Im Gegensatz zum In-Memory-Dateisystem- oder In-Memory-MongoDB-Testen, benötigen wir für die REST-Schnittstellen-Tests keine globalen Anpassungen an Vitest vorzunehmen. Wir können passend zur Controller-Datei direkt in der zugehörigen Controller-Testdatei arbeiten.
Beginnen wir damit, die Dev-Dependencies zu installieren:
npm install -D supertest
Ich gehe davon aus, dass du in deinem Code eine Express-App erstellst und für den Aufruf http.createServer(app) in einer Datei wie createApp.ts zurückgibst. Das benötigen wir, um einen Testagenten mit Supertest zu erstellen.
import supertest from 'supertest'
import createApp from '@/createApp'
const agent = supertest.agent(createApp())
Wie du siehst, ist das alles mit wenig Aufwand eingerichtet. Für die tägliche Nutzung habe ich ein paar Tipps mitgebracht, die dir vielleicht helfen.
Superagent REST-API-Helfer
CORS
Unter der Annahme, dass du deine Schnittstelle mit CORS-Headern ausstattest, hast du das in folgender Art eingerichtet:
app.use(
cors({
origin: '*', // reduce to your domain
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
preflightContinue: false,
optionsSuccessStatus: 204,
exposedHeaders: ['x-correlation-id', 'etag'],
}),
) // add CORS header for all requests
Für die Schnittstellentests gibt es einen Testhelfer, der das abtestet:
import supertest from 'supertest'
export default (agent: supertest.Agent, apiUrl: string) => {
describe('OPTIONS', () => {
it('should have headers set', async () => {
// act
const { status, headers } = await agent.options(apiUrl)
// assert
expect(status).toEqual(204)
expect(headers['access-control-allow-origin']).toBe('*')
expect(headers['access-control-allow-methods']).toBe('GET,HEAD,PUT,PATCH,POST,DELETE')
expect(headers['access-control-expose-headers']).toBe('x-correlation-id,etag')
})
})
}
assertCorsHeaders.ts prüft für eine gegebene URL mithilfe des Agenten die Header
Der dazugehörige Test sieht wie folgt aus:
const baseUrl = '/users'
describe('UserController', () => {
describe('GET all', () => {
const apiUrl = baseUrl
assertCorsHeaders(agent, baseUrl) // for the
// ...
})
describe('GET by id', () => {
const apiUrl = baseUrl + '/entity-id'
assertCorsHeaders(agent, apiUrl) // for get by id
// ..
})
})
Beispielhafte Struktur für das Testen des UserControllers
Ich mag die Verschachtelung der describe-Blöcke als Mittel zur Strukturierung meiner Tests. Über Tastenkürzel kann ich auf verschiedenen Ebenen Code-Folding aktivieren, sodass ich mittels Cmd+k+<level> eine klare Übersicht bekomme.

Im nächsten Post werde ich auf das Thema Authentifizierung in Verbindung mit Swagger und Tests eingehen. Das ist ein größerer Block – je nach Umfang teile ich die Inhalte auf mehrere Posts auf.