How to mock your javascript dependencies with jest?

How to mock your javascript dependencies with jest?

An easy guide about what I learned implementing mocks

·

2 min read

As I recently searched the web for learning how jest mocks are working I experienced that the official docs and other sources are very misunderstanding and the keywords spy and mock are often misused. In this tutorial I tell you how you should mock your dependencies to have less issues between tests with them.

Mock vs spy

The first issue is that there are spies and mocks in the jest testing framework. The main difference is in how the function is handled.

If you use jest.mock() you provide a path to an module and by default all of it's functions are mocked with jest.fn() so that means they become useless and we need to define which ones should have an actual implementation.

If you use the jest.spy() on a module you have to pass an module to the function and specify which function should be spied.

// mock_sample_user.test.tsx
jest.spyOn(MockSampleService.prototype, "mockTestValue")
   .mockResolvedValue(
      "hello mocked",
   );
// mock_sample_user.service.ts
export class MockSampleUserService {
  constructor(
    private mocksampleService = new MockSampleService(),
  ) {}

  public async resolveValue() {
    return await this.mocksampleService.mockTestValue();
  }
}
// mock_sample.service.service.ts
export class MockSampleService {
  public async mockTestValue() {
    return "hello not mocked";
  }
}

When you use this the mockTestValue() function will be called but an wrapper is placed around them which handles things like counting the calls of the function or replacing it's return value (like in the example above).

An advantage here is that the claring between tests is very much easier than with the jest.mock or jest.fn() function.

It is possible to update your jest.config.js with some keywords to let this happen automatical. This is very clean so that every test have it`s own scope like it should be in a classic unit test.

Just add these to your config file:

// jest.config.js
module.exports = {
   ...
   restoreMocks: true,  /* Automatically restore mock state before every test*/
   resetModules: true,  /* resets the module registry before running each test*/
   clearMocks: true,      /* clear mock calls and instances before every test*/
}

Now even if you use an jest.spy(...).mockImplementation() it gets cleared after the test.

Header image by David Travis