Mocking is creating artificial versions of functions, modules, or objects. In Jurassic Park, it is like creating dinosaur models for security tests instead of using real beasts.
jest.fn() creates an "empty" function that records all calls.1test('jest.fn() - basics', () => {
2 // Creating a mock function
3 const feedDino = jest.fn();
4
5 // Calling the mock function
6 feedDino('Rex', 'meat');
7 feedDino('Brachio', 'plants');
8
9 // Checking calls
10 expect(feedDino).toHaveBeenCalled();
11 expect(feedDino).toHaveBeenCalledTimes(2);
12 expect(feedDino).toHaveBeenCalledWith('Rex', 'meat');
13 expect(feedDino).toHaveBeenLastCalledWith('Brachio', 'plants');
14});You can give a mock a behavior:
1test('mock with implementation', () => {
2 // Mock with return value
3 const getHealth = jest.fn().mockReturnValue(100);
4 expect(getHealth()).toBe(100);
5
6 // Mock with different values for subsequent calls
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 with custom implementation
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() allows you to replace an entire module with a mock:1// File: alertService.js
2export function sendAlert(zone, message) {
3 // In reality sends email/SMS - we don't want this in tests!
4 return fetch('/api/alerts', {
5 method: 'POST',
6 body: JSON.stringify({ zone, message })
7 });
8}
9
10// File: securitySystem.test.js
11jest.mock('./alertService');
12
13const { sendAlert } = require('./alertService');
14
15describe('SecuritySystem', () => {
16 beforeEach(() => {
17 // Reset mocks before each test
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('breach')
29 );
30 });
31});spyOn monitors an existing method without replacing it (by default).1test('spyOn - monitoring a method', () => {
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 // Spy on the method - preserves original implementation
14 const spy = jest.spyOn(park, 'addDinosaur');
15
16 park.addDinosaur({ name: 'Rex' });
17 park.addDinosaur({ name: 'Blue' });
18
19 // Check calls
20 expect(spy).toHaveBeenCalledTimes(2);
21 expect(spy).toHaveBeenCalledWith({ name: 'Rex' });
22
23 // The original function still works!
24 expect(park.dinosaurs).toHaveLength(2);
25
26 // Restore original implementation
27 spy.mockRestore();
28});1test('spyOn - replacing implementation', () => {
2 const api = {
3 fetchDinoData(id) {
4 // Normal API call - we don't want this in tests
5 return fetch(`/api/dinosaurs/${id}`);
6 }
7 };
8
9 // Replace implementation for the duration of the test
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 // Now fetchDinoData returns mock data
19 api.fetchDinoData('001').then(data => {
20 expect(data.name).toBe('Mock Rex');
21 });
22
23 spy.mockRestore();
24});Jest provides a rich set of matchers for mocks:
1test('matchers for mocks', () => {
2 const callback = jest.fn();
3
4 callback('Rex');
5 callback('Blue', 'raptor');
6
7 // Was it called?
8 expect(callback).toHaveBeenCalled();
9
10 // How many times?
11 expect(callback).toHaveBeenCalledTimes(2);
12
13 // With what arguments?
14 expect(callback).toHaveBeenCalledWith('Rex');
15 expect(callback).toHaveBeenNthCalledWith(1, 'Rex');
16 expect(callback).toHaveBeenNthCalledWith(2, 'Blue', 'raptor');
17
18 // Access to call details
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});