2
votes

I'm using Jest to test a function from a service that uses axios to make some api calls. The problem is that Jest keeps calling the actual services function instead of the mocked service function. Here is all of the code:

The tests:

// __tests__/NotificationService.spec.js
const mockService = require('../NotificationService').default;

beforeEach(() => {
  jest.mock('../NotificationService');
});

describe('NotificationService.js', () => {
  it('returns the bell property', async () => {
    expect.assertions(1);
    const data = await mockService.fetchNotifications();
    console.log(data);
    expect(data).toHaveProperty('data.bell');
  });
});

The mock:

// __mocks__/NotificationService.js
const notifData = {
  bell: false,
  rollups: [
    {
      id: 'hidden',
      modifiedAt: 123,
      read: true,
      type: 'PLAYLIST_SUBSCRIBED',
      visited: false,
      muted: false,
      count: 3,
      user: {
        id: 'hidden',
        name: 'hidden'
      },
      reference: {
        id: 'hidden',
        title: 'hidden',
        url: ''
      }
    }
  ],
  system: [],
  total: 1
};

export default function fetchNotifications(isResolved) {
  return new Promise((resolve, reject) => {
    process.nextTick(() =>
      isResolved ? resolve(notifData) : reject({ error: 'It threw an error' })
    );
  });
}

The service:

import axios from 'axios';

// hardcoded user guid
export const userId = 'hidden';

// axios instance with hardcoded url and auth header
export const instance = axios.create({
  baseURL: 'hidden',
  headers: {
    Authorization:
      'JWT ey'
  }
});

/**
 * Notification Service
 * Call these methods from the Notification Vuex Module
 */
export default class NotificationService {

  /**
   * @GET Gets a list of Notifications for a User
   * @returns {AxiosPromise<any>}
   * @param query
   */
  static async fetchNotifications(query) {
    try {
      const res = await instance.get(`/rollups/user/${userId}`, {
        query: query
      });
      return res;
    } catch (error) {
      console.error(error);
    }
  }
}

I've tried a couple of variations of using require instead of importing the NotificationService, but it gave some other cryptic errors...

I feel like I'm missing something simple.

Help me please :)

1

1 Answers

0
votes

The problem is that Jest keeps calling the actual services function instead of the mocked service function.

babel-jest hoists jest.mock calls so that they run before everything else (even import calls), but the hoisting is local to the code block as described in issue 2582.

I feel like I'm missing something simple.

Move your jest.mock call outside the beforeEach and it will be hoisted to the top of your entire test so your mock is returned by require:

const mockService = require('../NotificationService').default;  // mockService is your mock...

jest.mock('../NotificationService');  // ...because this runs first

describe('NotificationService.js', () => {
  it('returns the bell property', async () => {
    ...
  });
});