mercredi 29 janvier 2020

Changing a jest mock on a specific test

I'm trying to write unit tests for a custom React hook that connects to Firebase. Since I don't want to actually connect to Firebase when running my tests, I've mocked Firebase and Firebase/app. They're super simple mocks, only returning the functions the code actually uses.

// __mocks__/firebase.js
export default {
  analytics: jest.fn(),
  storage: jest.fn()
};
// __mocks__/firebase/app.js
const auth = jest.fn().mockReturnValue({
  currentUser: {
    getIdTokenResult: jest.fn().mockReturnValue({
      claims: jest.fn()
    })
  },
  onIdTokenChanged: jest.fn()
});

export default {
  initializeApp: jest.fn(),
  auth
}

This works fine for some of my tests, but in some cases I need to change values in the mocked file. In a specific case, I want to make sure errors are caught if something goes wrong with Firebase, so I want to make the value of currentUser be false instead (which causes my hook to throw an error so I can test that.

However, I can't figure out how to change the mocked file for one specific test, while leaving it the same for the other tests.

Here's an example of my test file

import { renderHook, cleanup } from '@testing-library/react-hooks';
import useFirebase from 'src/App/useFirebase';

/*
 * For some reason, jest.mock('firebase') doesnt use my custom mock files,
 * so I have to explicitly tell jest which files to use
 */
jest.mock('firebase', () => jest.requireActual('../../../__mocks__/firebase'));
jest.mock('firebase/app', () => jest.requireActual('../../../__mocks__/firebase/app'));

afterEach(cleanup);

test('returns rejected promise if theres an error', async () => {

  // Trying to override the mocked module, with a slightly different one.
  // However, useFirebase.js still uses the first mocked module
  jest.mock('firebase/app', () => ({
    auth: jest.fn().mockReturnValue({
      currentUser: false
    }),
    initializeApp: jest.fn()
  }));

  expect.assertions(1);
  const { result } = renderHook(() => useFirebase());

  // verifyGroup is a function in useFirebase(), that I'm trying to make return
  // a rejected promise
  await result.current.verifyGroup()
    .catch(e => {
      expect(e).not.toBeNull();
    });
});

Nothing I seem to do causes useFirebase.js to use my second mock instead of my first one.

How can I achieve this?

Aucun commentaire:

Enregistrer un commentaire