What are mocks and stubs?
JavaScriptThe short answer
Mocks and stubs are fake versions of real dependencies used in tests. A stub provides preset return values so you can control what your code receives. A mock does everything a stub does but also tracks how it was called — you can check if a function was called, how many times, and with what arguments.
Why we need them
When testing a function, you often do not want to use real dependencies. If your function calls an API, you do not want to make actual network requests in tests — they are slow, unreliable, and depend on external services.
// This function depends on fetchasync function getUser(id) { const response = await fetch(`/api/users/${id}`); return response.json();}In tests, you replace fetch with a fake version that returns controlled data.
Stubs
A stub replaces a function with a version that returns a fixed value:
// Stub the fetch functionglobal.fetch = jest.fn(() => Promise.resolve({ json: () => Promise.resolve({ id: 1, name: 'John' }), }));test('getUser returns user data', async () => { const user = await getUser(1); expect(user.name).toBe('John');});The stub always returns the same user object. We do not care how fetch was called — we just need it to return something predictable.
Mocks
A mock is like a stub but also records how it was used:
const sendEmail = jest.fn();function registerUser(email) { // ... create user ... sendEmail(email, 'Welcome!');}test('sends welcome email on registration', () => { registerUser('john@example.com'); // Check that sendEmail was called correctly expect(sendEmail).toHaveBeenCalledTimes(1); expect(sendEmail).toHaveBeenCalledWith( 'john@example.com', 'Welcome!' );});We do not care what sendEmail actually does — we just want to verify it was called with the right arguments.
Spies
A spy watches a real function without replacing it:
const spy = jest.spyOn(console, 'log');doSomething();expect(spy).toHaveBeenCalledWith('Operation complete');spy.mockRestore(); // restore originalThe original function still runs, but we can check how it was called.
In practice with Jest
// jest.fn() — creates a mock functionconst mock = jest.fn();mock.mockReturnValue(42);// jest.spyOn() — spies on existing methodjest.spyOn(object, 'method');// jest.mock() — mocks an entire modulejest.mock('./api', () => ({ fetchUser: jest.fn(() => Promise.resolve({ name: 'John' }) ),}));When to use what
- Stubs — when you need a dependency to return specific data
- Mocks — when you want to verify a function was called correctly
- Spies — when you want to observe a real function without changing it
Interview Tip
The key distinction is: stubs control input (what your code receives), mocks verify output (what your code does). Give a simple example for each. Knowing Jest's API (jest.fn(), jest.spyOn(), jest.mock()) shows hands-on testing experience.
Why interviewers ask this
This question tests if you have practical testing experience. Interviewers want to see if you can isolate dependencies in tests, if you know the difference between stubs and mocks, and if you can use them effectively. It shows you write testable code and think about test quality.