Node.js mit TSOA und Authentifizierung - (Teil 8) Der Unit-Test

Ich bereite die Express-Applikation für den ersten Unit-Test vor. Dank der bisherigen Vorbereitung kann das Versprechen vom ersten Artikel eingelöst werden: einzeilige Absicherung und einzeiliges Testen der Absicherung. So bauen wir künftig bessere Applikationen. Test frei!

3 Minuten

In diesem Artikel schreiben wir den Unit-Test für den gesicherten Endpunkt. Der Vitest-Helfer ist vorbereitet. Somit bleiben der Test und das Setup für die Aufrufe. Bevor wir anfangen, empfiehlt es sich, die Vorgänger der Artikelserie zu lesen:

Anpassung der Express-Applikation

Damit wir die Express-Applikation mithilfe von Supertest testen können, benötigen wir die Applikation als Export. Dafür erstellen wir eine Datei namens createApp.ts, deren Export unsere bisherige Express-Applikation liefert.

import express from 'express'  
import { RegisterRoutes } from '@/routes'  
import { DefaultMappingStrategy, MapperRegistry } from 'http-problem-details-mapper'  
import { UnauthenticatedMapper } from '@/errors/UnauthenticatedError'  
import { UnauthorizedMapper } from '@/errors/UnauthorizedError'  
import { DefaultErrorMapper } from '@/errors/DefaultErrorMapper'  
import HttpProblemResponse from '@/errors/HttpProblemResponse'  

const createApp = (): express.Express => {  
  const mapperRegistry = new MapperRegistry()  
    .registerMapper(new UnauthenticatedMapper())  
    .registerMapper(new UnauthorizedMapper())  
    .registerMapper(new DefaultErrorMapper())  
  const ErrorMappingStrategy = new DefaultMappingStrategy(mapperRegistry)  

  const app = express()  
  RegisterRoutes(app)  

// The RFC 7807 error middleware has to be the last app.use() to work as intended  
// It will map the thrown errors to the RFC applying responses  
  app.use(HttpProblemResponse({strategy: ErrorMappingStrategy}))  

  return app  
}  

export default createApp

Das Ergebnis binden wir in index.ts ein:

import createApp from '@/createApp'  

const PORT = process.env.PORT || 4000  
const app = createApp()  

app.listen(PORT, () => {  
  console.log(`Server is listening on port ${PORT}`)  
})

Skript in der Package.json

Für die schnelle Ausführung der Tests aktualisieren wir die package.json um folgende zwei Zeilen:

"scripts": {  
  "test": "vitest run",  
  "test:watch": "vitest"  
},

Die erste führt die Tests einmalig aus, die zweite lässt sie im Watch-Mode laufen. Letzterer eignet sich für testgetriebene Entwicklung.

Der eigentliche Unit-Test

Wir haben soweit alles vorbereitet und schreiben jetzt den Unit-Test. Im Rahmen des Tests mocken wir die Authentication-Middleware, binden unsere Express-Applikation in Supertest ein und simulieren die Aufrufe. Der Mock stellt sicher, dass wir nicht die eigentliche Middleware prüfen, sondern nur den korrekten Aufruf. Die Middleware-Tests folgen später.

Hier ist der Unit-Test in seiner Gesamtheit mit allen Imports und dem Mock.

import supertest from 'supertest'  
import createApp from '@/createApp'  
import { expressAuthentication } from '@/services/AuthMiddleware'  
import { MockedFunction } from 'vitest'  

const agent = supertest.agent(createApp())  

vi.mock('@/services/AuthMiddleware')  
const mockExpressAuthentication = expressAuthentication as MockedFunction<typeof expressAuthentication>  

describe('EntityController', () => {  
  it('should validate secure route is accessible by ADMIN', async () => {  
    // act  
    await agent.get('/entities')  

    // assert  
    expect(mockExpressAuthentication).toHaveBeenCalledWithRequiredScopes(['ADMIN'])  
  })  
})

Fazit

Mit dem Aufruf der Tests können wir sicherstellen, dass die @Security-Deklaration den Erwartungen entspricht. Der Aufruf von npm run test liefert das passende Ergebnis:

❯ npm run test

> nodejs_tsoa_auth@1.0.0 test
> vitest run


 RUN  v4.0.16 /Users/markschmeiser/WebstormProjects/nodejs_tsoa_auth

 ✓ tests/entities/EntitiyController.spec.ts (1 test) 10ms
   ✓ EntityController (1)
     ✓ should validate secure route is accessible by ADMIN 10ms

 Test Files  1 passed (1)
      Tests  1 passed (1)
   Start at  15:52:41
   Duration  457ms (transform 65ms, setup 19ms, import 353ms, tests 10ms, environment 0ms)

In einem weiteren Artikel werde ich die Express-Middleware prüfen. Die korrekte Ausführung der Scope-Vergleiche ist entscheidend für die Sicherheit der Applikation.

call to action background image

Abonniere meinen Newsletter

Erhalte einmal im Monat Nachrichten aus den Bereichen Softwareentwicklung und Kommunikation gespikt mit Buch- und Linkempfehlungen.