Learning Outcomes - 15th April
Mocking with jest
This past week I’ve learnt a couple of handy things about Mocking with jest. Before I go into what I’ve leant, mocking with jest has really simplified my testing in the front, specifically React. After learning TDD, you develop the urge to test everything you are going to write, and whilst practising TDD, you find that you have to mock out some of the behaviours of certain objects because you have either haven’t yet implemented implemented it or you want to isolate and test a specific functionality independent of other dependencies. Sometimes you may even end up testing the mocked code (writing tests for your test code) and this takes a lot time.
Either way, jest can create mocked functions using jest.fn() which is pretty cool. It can specify the parameters the function expects and even the return type. This makes testing easier and significantly faster. Let me dive into 2 handy functions in jest that have simplified testing for me:
Jest.mock()
This function can be used when you want to mock aa function that isn’t being passed as a dependency. Say you were testing a component, Board, and you want to test that it calls a function named displayBoard(). You can simply mock the function such that it doesn’t have to worry about the actual implementation of displayBoard but rather its signature.
//board.test.js import Board from './board'; jest.mock('./board'); import { displayBoard } from './board' describe("Board", () => { it("calls displayBoard", () => { const wrapper = shallow(<Board />); expect(displayBoard).toHvaeBeenCalled(); }); });
// board.js export function displayBoard() { . . . } const function Board() { return ({ <div> displayboard() </div> }) } export default Board;
The jest.mock() function is mocking all the subsequent imports from board.js.
To disable the automatic mocks, you can add jest.disableAutomock() so that you can import other functions from that file.
2. Jest.spyOn()This is similar to jest.fn() but also tracks calls made on the object. The entity on the object being spied on must exists.
// video.test.js import video from './video'; test('plays video', () => { const spy = jest.spyOn(video, 'play'); const isPlaying = video.play(); expect(spy).toHaveBeenCalled(); expect(isPlaying).toBe(true); });
// video.js const function video () { play() { return true; }, }; export default video;
Here, we don’t want to actually execute play inside the video object. The difference between this and jest.mock is that this can only spy on a specific entity in an object, whereas mock would mock the entire object. So, if there was another entity inside the video object. It would have its full functionality accessible inside the tests as shown below.
// video.js const function video() { play() { return true; }, resume() { . . .}, // functionality can be accessed inside the test if spying on play }; export default video;