Node.js Test-Tipps - Dateisystem
Ein wichtiger Baustein bei der Entwicklung sind die Unittests. Im Kontext von Node.js nutze ich vitest. Ich möchte euch heute zeigen, wie ich bei der Arbeit mit dem Dateisystem vorgehe. Dafür gibt es ein paar Kniffe, die das Leben enorm erleichtern.
Bei der Arbeit mit Node.js und dem Dateisystem kann ich für die Tests empfehlen, mit einem In-Memory-Dateisystem zu arbeiten. Das hat zwei Gründe:
- Das In-Memory-Dateisystem ist superschnell im Vergleich zu Zugriffen auf das echte Dateisystem – auch in Zeiten wirklich schneller Festplatten.
- Das In-Memory-Dateisystem ermöglicht es, die Vor- und Nachbedingungen innerhalb eines Tests zu definieren, sodass dieser isoliert von allen anderen Tests ausführbar ist. Besser noch: Mehrere Tests können parallel laufen und in ihrem eigenen virtuellen Dateisystem Änderungen vornehmen.
Wie es in der IT üblich ist, ist auch Schatten, wo Licht ist. Ein wesentlicher Nachteil der mir bekannten Pakete ist, dass das Rechtesystem nicht oder nur teilweise abgebildet ist. Damit lassen sich also Zugriffsrechte, wer was darf, nicht abtesten. Hierfür habe ich noch keinen sinnvollen Ansatz gefunden. Wenn du also Ideen hast, lass mir gerne einen Kommentar da.
Notwendige Installation und Konfiguration
Ich arbeite mit dem NPM-Paket memfs. Für die Einbindung gilt es, die internen Node.js-Bibliotheken zu mocken. Das machst du am besten in einer setup.ts, die du in vitest konfigurierst. Zum Abrunden meines letzten Tippes: Stelle das Reset des In-Memory-Dateisystems einmalig global sicher. Das spart dir viel Debug-Zeit. Das habe ich für dich ausprobiert 😉.
export default {
test: {
// ...
setupFiles: [
'tests/helper/setupTests.ts',
]
// ...
},
}
Ein Ausschnitt der vitest.config.js
// --- tests/helper/setupTest.ts
// mock fs
vi.mock('node:fs', async () => {
const memfs: { fs: typeof fs } = await vi.importActual('memfs')
return { default: memfs.fs, ...memfs.fs }
})
// mock fs.promises
vi.mock('node:fs/promises', async () => {
const memfs: { fs: typeof fs } = await vi.importActual('memfs')
return { default: memfs.fs.promises, ...memfs.fs.promises }
})
// reset the state of in-memory fs on each test
beforeEach(() => {
vol.reset()
})
Das Mocken von Node.js und der Standard-Rest
Du nutzt noch Jest und denkst darüber nach, zu wechseln? Oder du möchtest ein paar mehr Details zur Memfs-Nutzung lesen, dann findest du weitere Ideen in meinem Artikel „Recap – ViTest statt Jest.“