Node.js dla początkujących - Część 16: Testy jednostkowe - Jest

1/22/2025 Kurs JavaScript

Mateusz Kędziora

image

Hej! Witaj w kolejnym artykule z naszego kursu JavaScript dla początkujących. Dziś zanurzymy się w temat testowania Twojego kodu, a konkretnie – testowania aplikacji Node.js za pomocą popularnego frameworka Jest. Zastanawiasz się pewnie, po co w ogóle testować kod? Wyobraź sobie, że budujesz skomplikowany program, który ma wiele funkcji. Zmiana jednej linijki kodu może nieoczekiwanie zepsuć coś w zupełnie innym miejscu. Testy pozwalają nam tego uniknąć, dając pewność, że nasz kod działa zgodnie z oczekiwaniami.

Dlaczego Jest?

Jest to wszechstronny framework testowy, który oferuje wszystko, czego potrzebujemy do testowania kodu JavaScript, zarówno po stronie klienta (w przeglądarce), jak i po stronie serwera (Node.js). Jest szybki, łatwy w konfiguracji i oferuje wiele przydatnych funkcji, takich jak:

  • Szybkie uruchamianie testów: Jest uruchamia testy równolegle, co znacznie skraca czas oczekiwania na wyniki.
  • Wbudowane mockowanie: Umożliwia łatwe izolowanie testowanego kodu od zależności zewnętrznych.
  • Łatwa konfiguracja: Nie wymaga skomplikowanej konfiguracji, co pozwala szybko rozpocząć pisanie testów.
  • Doskonała dokumentacja: Posiada rozbudowaną i czytelną dokumentację.

Wprowadzenie

Instalacja Jest

Zacznijmy od instalacji. Jeśli masz już zainstalowany Node.js i npm (Node Package Manager), otwórz terminal i w katalogu projektu wykonaj polecenie:

npm install --save-dev jest

Flaga --save-dev oznacza, że Jest zostanie zainstalowany jako zależność deweloperska (nie będzie potrzebny w finalnej wersji aplikacji).

Pierwszy test jednostkowy

Stwórzmy prosty moduł, który będzie zawierał funkcję dodającą dwie liczby:

// math.js
function add(a, b) {
  return a + b;
}

module.exports = add;

Teraz stwórzmy plik testowy o nazwie math.test.js (konwencja nazewnicza: nazwa_pliku.test.js lub nazwa_pliku.spec.js):

// math.test.js
const add = require('./math');

test('dodawanie 2 i 3 powinno dać 5', () => {
  expect(add(2, 3)).toBe(5);
});

Omówienie testu

  • const add = require('./math'); – importujemy funkcję add z naszego modułu.
  • test('opis testu', () => { ... }); – definiujemy test. Opis testu powinien być krótki i zwięzły, a jednocześnie precyzyjnie opisywać, co jest testowane.
  • expect(add(2, 3)).toBe(5); – to tzw. asercja. Sprawdzamy, czy wynik wywołania funkcji add(2, 3) jest równy 5. toBe() to jeden z wielu dostępnych matcherów (funkcji porównujących).

Uruchamianie testów

Aby uruchomić testy, dodaj do pliku package.json w sekcji scripts następujący wpis:

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

Teraz w terminalu możesz wykonać polecenie:

npm test

Powinieneś zobaczyć wynik testu, informujący o tym, czy test zakończył się sukcesem (PASS) czy porażką (FAIL).

Inne matchery

Oprócz toBe() Jest oferuje wiele innych matcherów, np.:

  • toBeGreaterThan(number): Sprawdza, czy wartość jest większa od podanej liczby.
  • toBeLessThan(number): Sprawdza, czy wartość jest mniejsza od podanej liczby.
  • toEqual(value): Sprawdza, czy wartość jest równa podanej wartości (działa również dla obiektów i tablic).
  • toContain(item): Sprawdza, czy tablica zawiera dany element.
  • toThrow(error): Sprawdza, czy funkcja rzuca wyjątek.

Przykład z użyciem toEqual():

test('obiekty są równe', () => {
  const data = { one: 1 };
  data['two'] = 2;
  expect(data).toEqual({ one: 1, two: 2 });
});

Testowanie funkcji asynchronicznych

Do testowania funkcji asynchronicznych możemy użyć async/await lub promises.

Przykład z async/await:

async function fetchData() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('dane');
    }, 100);
  });
}

test('pobieranie danych asynchronicznie', async () => {
  const data = await fetchData();
  expect(data).toBe('dane');
});

Mockowanie

Mockowanie pozwala nam izolować testowany kod od zależności zewnętrznych, takich jak bazy danych, API czy inne moduły. Jest oferuje wbudowane mechanizmy mockowania.

Przykład mockowania modułu:

// api.js
function getDataFromApi() {
  // Symulacja pobierania danych z API
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({ message: 'Dane z API' });
    }, 100);
  });
}

module.exports = { getDataFromApi };

// api.test.js
const { getDataFromApi } = require('./api');

jest.mock('./api', () => ({
  getDataFromApi: jest.fn(() => Promise.resolve({ message: 'Mockowane dane' })),
}));

test('test z mockowaniem API', async () => {
  const data = await getDataFromApi();
  expect(data.message).toBe('Mockowane dane');
  expect(getDataFromApi).toHaveBeenCalled(); // Sprawdzamy, czy funkcja mock została wywołana
});

W tym przykładzie zamockowaliśmy funkcję getDataFromApi, zwracając zamiast rzeczywistych danych, mockowane dane. Dzięki temu test jest niezależny od stanu API.

Grupy testów (describe)

Możemy grupować testy za pomocą funkcji describe. To pomaga w organizacji testów i poprawia ich czytelność.

describe('Testy funkcji dodawania', () => {
  test('dodawanie 2 i 3 powinno dać 5', () => {
    expect(add(2, 3)).toBe(5);
  });

  test('dodawanie -1 i 1 powinno dać 0', () => {
    expect(add(-1, 1)).toBe(0);
  });
});

Praca domowa

  1. Stwórz moduł, który będzie zawierał funkcję obliczającą pole prostokąta.
  2. Napisz testy jednostkowe dla tej funkcji, używając różnych matcherów (np. toBe(), toBeGreaterThan()).
  3. Stwórz moduł, który będzie pobierał dane z fikcyjnego API (możesz użyć setTimeout do symulacji opóźnienia).
  4. Napisz testy, mockując funkcję pobierającą dane z API.
  5. Pogrupuj testy za pomocą describe.

Podsumowanie

Testowanie to kluczowy element procesu tworzenia oprogramowania. Dzięki Jest możemy pisać testy jednostkowe w sposób prosty i efektywny, zapewniając wysoką jakość naszego kodu. Zachęcam Cię do dalszego eksperymentowania z Jest i odkrywania jego możliwości. Pamiętaj, że praktyka czyni mistrza!

Dodatkowe wskazówki

  • Staraj się pisać testy przed napisaniem kodu (TDD – Test-Driven Development).
  • Pisz testy dla każdego przypadku użycia, w tym dla przypadków brzegowych i błędnych danych wejściowych.
  • Dbaj o to, aby testy były krótkie, zwięzłe i czytelne.
  • Regularnie uruchamiaj testy, aby szybko wykrywać błędy.

Mam nadzieję, że ten artykuł był dla Ciebie pomocny. Jeśli masz jakieś pytania, śmiało zadawaj

Polecane artykuły