They are all test doubles: objects that stand in for a real dependency. They differ in what they do and in what you check.
One running example: your component calls getUser() from an API module.
- A stub returns a canned answer. Your
getUserstub always resolves to{ name: 'Ana' }. You use it to put the code into a state, here "user loaded". You don't assert on the stub itself. - A spy records how it was called.
jest.spyOn(api, 'getUser')wraps the realgetUser. By default it keeps the original behaviour, so the real request still runs. Afterwards you can check how many times it ran and with which arguments. - A mock is a double you set expectations on. You check it was called in a certain way, for example
expect(getUser).toHaveBeenCalledWith(42). The call itself is what you test. - A fake is a working but simplified implementation. For example, an in-memory user store that
getUserreads from. Fake timers and MSW acting as a fake server are fakes too.
In Jest, one jest.fn() can be both a stub and a mock. Give it mockResolvedValue to stub it, and assert its calls to use it as a mock.
In practice: stub the inputs and assert on the outputs. Assert on calls only when the call is the behaviour, like onSubmit.
- Stubs, spies, mocks and fakes are all test doubles that stand in for a real dependency.
- A stub returns canned answers, like
getUseralways resolving to Ana. - A spy records calls and can keep the real implementation running.
- A mock is a double you assert expectations on, like checking
getUserwas called with 42. - A fake is a lightweight working version, like an in-memory store, fake timers or MSW.
Read more