Hjem » Siste artikler » Slik bruker du Jest i Node-prosjekter for trygg refaktorering uten manuelt klikkearbeid

Slik bruker du Jest i Node-prosjekter for trygg refaktorering uten manuelt klikkearbeid

Hovedillustrasjon
Hovedillustrasjon. Foto: James Harrison / Unsplash.

Jo mer kode et prosjekt får, jo skumlere føles det å endre ting. Små justeringer i én modul kan plutselig knekke noe helt annet, og man ender fort opp med å teste alt manuelt i nettleser eller via API-kall.

Her kan Jest være et veldig nyttig verktøy for Node-baserte prosjekter. Med et fornuftig oppsett får du raske tilbakemeldinger på endringer, mindre manuelt klikkearbeid og mer trygghet når du refaktorerer.

Hva er Jest, og når passer det?

Jest er et testverktøy for JavaScript og TypeScript som særlig brukes sammen med Node og frontends som React. Det gir deg én pakke som håndterer testrunner, assertions, mocking og coverage.

I rene Node-prosjekter passer Jest godt når du vil teste:

  • Forretningslogikk (funksjoner, domeneobjekter, validering)
  • Små moduler som opererer på data, filer eller API-responser
  • Enkle integrasjoner mot HTTP-klienter, databaser og køer (ofte med mocking)

Hvis du primært tester hele systemer via HTTP, kan dedikerte end-to-end verktøy være et bedre valg. Men som sikkerhetsnett rundt selve koden gir Jest mye verdi med lite oppsett.

Grunnoppsett i et eksisterende Node-prosjekt

La oss ta utgangspunkt i et typisk Node-prosjekt som bruker npm og moderne JavaScript eller TypeScript. Målet er å komme i gang uten en stor konfigurasjonsjobb.

Start med å installere Jest som utviklingsavhengighet:

Med npm:npm install --save-dev jest
Med pnpm:pnpm add -D jest
Med Yarn:yarn add --dev jest

Enkel package.json-konfig

Deretter legger du til et testscripts i package.json:

"scripts": { "test": "jest" }

Hvis du bruker rene .js-filer uten moduler og transpiling, holder dette ofte. Jest vil automatisk lete etter filer som slutter på .test.js eller .spec.js.

Prosjekter med ESM eller TypeScript

Bruker du ESM ("type": "module") eller TypeScript, må du typisk legge til litt ekstra. Et vanlig mønster for TypeScript er:

  • Bruke ts-jest for å la Jest forstå .ts-filer
  • Konfigurere en enkel jest.config.cjs for å holde ting adskilt

Her er det lurt å følge oppdatert dokumentasjon, siden støtte for ESM og nye Node-versjoner endrer seg over tid. Sjekk alltid de nyeste anbefalingene før du låser deg til en løsning.

Struktur: hvor legger du testene?

Hvordan du organiserer testfiler har mye å si for hvor lett det blir å holde oversikt. To ganske vanlige mønstre er:

  • Samme mappe som kildekoden: src/userService.js og src/userService.test.js
  • Egen testmappe: src/userService.js og tests/userService.test.js

Fordelen med å ha testene ved siden av koden er at det er lett å se hva som hører sammen, og at refaktorering av filstruktur ofte blir enklere.

En første Jest-test steg for steg

Anta at du har en modul math.js:

export function sum(a, b) { return a + b; }

Lag en testfil math.test.js ved siden av:

import { sum } from './math';

test('sum legger sammen to tall', () => {
  expect(sum(2, 3)).toBe(5);
});

Nå kan du kjøre npm test og se at Jest finner og kjører testen. Hver test består typisk av tre deler: oppsett, handling og forventning.

Gjør tester lesbare, ikke “smarte”

En liten tommelfingerregel er at hver test bør være enkel å skumme. Gode navn og lite støy gjør at du raskere forstår hva som feiler når noe går galt. Heller flere korte tester enn én altfor generell.

Tester forretningslogikk i praksis

Tematisk illustrasjon
Tematisk illustrasjon. Foto: Joan Gamell / Unsplash.

La oss si du har en modul som regner ut rabatt basert på ordreverdi:

export function calculateDiscount(amount) {
  if (amount < 500) return 0;
  if (amount < 1000) return 0.05;
  return 0.1;
}

I testen kan du beskrive casene eksplisitt:

import { calculateDiscount } from './discount';

describe('calculateDiscount', () => {
  it('gir 0 rabatt under 500', () => {
    expect(calculateDiscount(499)).toBe(0);
  });

  it('gir 5% mellom 500 og 999', () => {
    expect(calculateDiscount(500)).toBe(0.05);
    expect(calculateDiscount(999)).toBe(0.05);
  });
});

Poenget er at du låser innreglene i kode, slik at en fremtidig refaktorering ikke endrer forretningslogikk ved et uhell.

Mocking: når og hvordan bruke det fornuftig

I Node-prosjekter må du ofte forholde deg til moduler som treffer verden utenfor: databaser, HTTP-klienter, filsystem og meldingskøer. Her er det sjelden lurt å kjøre ekte kall i enhetstester.

Jest har innebygget støtte for mocking av moduler. Et enkelt eksempel med en HTTP-klient:

import { fetchUser } from './userService';
import { httpClient } from './httpClient';

jest.mock('./httpClient');

test('fetchUser returnerer data fra httpClient', async () => {
  httpClient.get.mockResolvedValue({ id: 1, name: 'Test' });

  const user = await fetchUser(1);
  expect(user.name).toBe('Test');
});

Her tester du din egen logikk rundt HTTP-kallet, uten å være avhengig av nettverk eller et eksternt API.

Unngå over-mocking

Samtidig er det lett å mocke for mye. Hvis du mocker hele verden, tester du kanskje bare at mockene oppfører seg slik du har definert dem. Et par enkle retningslinjer:

  • Mock ting utenfor din kontroll (eksterne tjenester, systemklokke, tilfeldighet)
  • La intern domenelogikk gå “ekte” så langt det lar seg gjøre
  • Vurder egne integrasjonstester for viktige kjeder gjennom systemet

Testkjøring i hverdagsflyt: watch mode og filtrering

En stor del av verdien med Jest ligger i hvordan du kjører testene mens du utvikler. Standardskriptet npm test kan utvides for å støtte mer smidig arbeidsflyt.

En nyttig variant er watch mode:

"scripts": { "test": "jest --watch" }

Da kjøres testene på nytt automatisk når du lagrer filer, gjerne bare for berørte moduler. Dette gir rask feedback når du endrer ting.

Kjøre bare noen tester

Når prosjektet vokser, blir det upraktisk å kjøre absolutt alt hele tiden. Du kan:

  • Kjøre tester i en spesifikk fil: jest userService.test.js
  • Bruke test.only midlertidig på én test
  • Filtrere på navn: jest -t "calculateDiscount"

Poenget er å bruke Jest som et raskt verktøy mens du jobber, ikke bare som et steg i CI.

Integrasjon med Git og CI

For at testene skal gi reell trygghet, må de kjøre oftere enn “når noen husker det”. To enkle grep du kan vurdere:

  • Kjør npm test i CI på hver branch og pull request
  • Bruk Git hooks (for eksempel pre-push) for å kjøre et mindre testutvalg lokalt

Vær forsiktig med å gjøre hooks for tunge, da blir de ofte skrudd av. Prioriter raske enhetstester lokalt, og la CI ta den fulle runden med coverage og eventuelle integrasjonstester.

Vanlige fallgruver og hvordan unngå dem

Noen typiske problemer som dukker opp i Jest-oppsett i Node-prosjekter er:

  • Hengende tester: ofte forårsaket av åpne timere, sockets eller databasetilkoblinger som ikke lukkes
  • Avhengighet på rekkefølge: tester som “forurenser” global tilstand, for eksempel miljøvariabler eller singletons
  • Konfigurasjonskaos: mange gamle Jest-innstillinger og custom løsninger etter flere års patching

En god strategi er å holde testene små, eksplisitte og uavhengige. Rydd heller opp i oppsettet en gang i blant, enn å legge på flere lag med spesialtilpasninger hver gang noe skurrer.

En enkel sjekkliste for å komme i gang

Hvis du vil introdusere Jest i et eksisterende Node-prosjekt uten å bremse alt, kan du ta det i små steg:

  • Installer Jest og legg til et enkelt testscripts
  • Velg én mappe eller modul du kjenner godt, og skriv noen få enkle enhetstester
  • Få på plass watch mode i din lokale arbeidsflyt
  • Legg til Jest i CI for prosjektet, gjerne kun på en egen test- eller feature-branch først
  • Bygg gradvis ut testene rundt mest kritisk forretningslogikk

Da får du en testbase som vokser sammen med prosjektet, i stedet for et massivt testprosjekt som aldri blir ferdig.

0 kommentarer