Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

Mockowanie w Jest

Mockowanie to tworzenie sztucznych wersji funkcji, modułów lub obiektów. W Parku Jurajskim to jak tworzenie modeli dinozaurów do testów bezpieczeństwa zamiast używania prawdziwych bestii.

jest.fn() - tworzenie mock funkcji

jest.fn()
tworzy "pustą" funkcję, która rejestruje wszystkie wywołania.

1test('jest.fn() - podstawy', () => {
2  // Tworzenie mock funkcji
3  const feedDino = jest.fn();
4
5  // Wywołanie mock funkcji
6  feedDino('Rex', 'meat');
7  feedDino('Brachio', 'plants');
8
9  // Sprawdzanie wywołań
10  expect(feedDino).toHaveBeenCalled();
11  expect(feedDino).toHaveBeenCalledTimes(2);
12  expect(feedDino).toHaveBeenCalledWith('Rex', 'meat');
13  expect(feedDino).toHaveBeenLastCalledWith('Brachio', 'plants');
14});

Mock z implementacją

Możesz nadać mockowi zachowanie:

1test('mock z implementacją', () => {
2  // Mock z wartością zwracaną
3  const getHealth = jest.fn().mockReturnValue(100);
4  expect(getHealth()).toBe(100);
5
6  // Mock z różnymi wartościami dla kolejnych wywołań
7  const checkSensor = jest.fn()
8    .mockReturnValueOnce('OK')
9    .mockReturnValueOnce('WARNING')
10    .mockReturnValueOnce('DANGER');
11
12  expect(checkSensor()).toBe('OK');
13  expect(checkSensor()).toBe('WARNING');
14  expect(checkSensor()).toBe('DANGER');
15
16  // Mock z własną implementacją
17  const calculateDamage = jest.fn((attack, defense) => {
18    return Math.max(0, attack - defense);
19  });
20
21  expect(calculateDamage(50, 30)).toBe(20);
22  expect(calculateDamage(10, 30)).toBe(0);
23});

jest.mock() - mockowanie modułów

jest.mock()
pozwala zastąpić cały moduł mockiem:

1// Plik: alertService.js
2export function sendAlert(zone, message) {
3  // W rzeczywistości wysyła email/SMS - nie chcemy tego w testach!
4  return fetch('/api/alerts', {
5    method: 'POST',
6    body: JSON.stringify({ zone, message })
7  });
8}
9
10// Plik: securitySystem.test.js
11jest.mock('./alertService');
12
13const { sendAlert } = require('./alertService');
14
15describe('SecuritySystem', () => {
16  beforeEach(() => {
17    // Resetuj mocki przed każdym testem
18    sendAlert.mockClear();
19    sendAlert.mockResolvedValue({ status: 'sent' });
20  });
21
22  it('should send alert on breach', async () => {
23    const system = new SecuritySystem();
24    await system.reportBreach('Zone A');
25
26    expect(sendAlert).toHaveBeenCalledWith(
27      'Zone A',
28      expect.stringContaining('naruszenie')
29    );
30  });
31});

jest.spyOn() - szpiegowanie metod

spyOn
monitoruje istniejącą metodę bez jej zastępowania (domyślnie).

1test('spyOn - monitorowanie metody', () => {
2  const park = {
3    dinosaurs: [],
4    addDinosaur(dino) {
5      this.dinosaurs.push(dino);
6      return this.dinosaurs.length;
7    },
8    getDinosaurCount() {
9      return this.dinosaurs.length;
10    }
11  };
12
13  // Szpieguj metodę - zachowuje oryginalną implementację
14  const spy = jest.spyOn(park, 'addDinosaur');
15
16  park.addDinosaur({ name: 'Rex' });
17  park.addDinosaur({ name: 'Blue' });
18
19  // Sprawdź wywołania
20  expect(spy).toHaveBeenCalledTimes(2);
21  expect(spy).toHaveBeenCalledWith({ name: 'Rex' });
22
23  // Oryginalna funkcja nadal działa!
24  expect(park.dinosaurs).toHaveLength(2);
25
26  // Przywróć oryginalną implementację
27  spy.mockRestore();
28});

spyOn z podmianą implementacji

1test('spyOn - podmiana implementacji', () => {
2  const api = {
3    fetchDinoData(id) {
4      // Normalne wywołanie API - nie chcemy tego w testach
5      return fetch(`/api/dinosaurs/${id}`);
6    }
7  };
8
9  // Zastąp implementację na czas testu
10  const spy = jest.spyOn(api, 'fetchDinoData').mockImplementation((id) => {
11    return Promise.resolve({
12      id,
13      name: 'Mock Rex',
14      species: 'T-Rex'
15    });
16  });
17
18  // Teraz fetchDinoData zwraca mock data
19  api.fetchDinoData('001').then(data => {
20    expect(data.name).toBe('Mock Rex');
21  });
22
23  spy.mockRestore();
24});

Sprawdzanie wywołań mock

Jest udostępnia bogaty zestaw matcherów dla mocków:

1test('matchery dla mocków', () => {
2  const callback = jest.fn();
3
4  callback('Rex');
5  callback('Blue', 'raptor');
6
7  // Czy został wywołany?
8  expect(callback).toHaveBeenCalled();
9
10  // Ile razy?
11  expect(callback).toHaveBeenCalledTimes(2);
12
13  // Z jakimi argumentami?
14  expect(callback).toHaveBeenCalledWith('Rex');
15  expect(callback).toHaveBeenNthCalledWith(1, 'Rex');
16  expect(callback).toHaveBeenNthCalledWith(2, 'Blue', 'raptor');
17
18  // Dostęp do szczegółów wywołań
19  expect(callback.mock.calls).toHaveLength(2);
20  expect(callback.mock.calls[0]).toEqual(['Rex']);
21  expect(callback.mock.calls[1]).toEqual(['Blue', 'raptor']);
22});
Przejdź do CodeWorlds