1

I am trying to mock the init method provided by sentry-expo and so far, this is what I have come up with:

setupFilesAfterEnv.ts

import '@testing-library/jest-native/extend-expect';
import * as Sentry from 'sentry-expo';
import sentryTestkitSuite from 'sentry-testkit';

const DUMMY_DSN = 'https://acacaeaccacacacabcaacdacdacadaca@sentry.io/000001';

const { sentryTransport } = sentryTestkitSuite();

// https://stackoverflow.com/questions/44649699/service-mocked-with-jest-causes-the-module-factory-of-jest-mock-is-not-allowe
// Cannot use the imported module as a value directly
const mockSentryTransport = sentryTransport as jest.Mocked<
  typeof sentryTransport
>;

jest.mock('sentry-expo', () => ({
  ...jest.requireActual('sentry-expo'),
  init: (options?: Sentry.SentryExpoNativeOptions) => ({
    ...options,
    transport: mockSentryTransport,
  }),
}));

beforeAll(() =>
  Sentry.init({
    dsn: DUMMY_DSN,
    release: 'test',
    tracesSampleRate: 1,
    beforeSend(event) {
      return {
        ...event,
        extra: { os: 'mac-os' },
      };
    },
  }),
);

beforeEach(() => {
  sentryTestkitSuite().testkit.reset();
});

All the test cases which have used Sentry to capture exceptions successfully pass.

Now, I have created a file for adding standard crash-reporting utilities:

crash-reporting.ts

import * as Sentry from 'sentry-expo';

import { getEnvironmentConfig } from '@utils/environment/environment';

const routingInstrumentation =
  new Sentry.Native.ReactNavigationInstrumentation();

export const initialiseCrashReporting = () => {
  return Sentry.init({
    dsn: getEnvironmentConfig()?.sentryDSN,

    // Enable it only when you install the Expo development build on your device/simulator
    // If you enable it while running the app in Expo Go, native dependencies will not work as expected such as Sentry
    enableInExpoDevelopment: __DEV__,
    debug: __DEV__, // If `true`, Sentry will try to print out useful debugging information if something goes wrong with sending the event. Set it to `false` in production,
    environment: getEnvironmentConfig()?.appEnv ?? 'development',
    tracesSampleRate: __DEV__ ? 1 : 0.2,
    integrations: [
      new Sentry.Native.ReactNativeTracing({
        tracingOrigins: ['localhost', /^\//],
        routingInstrumentation,
      }),
    ],
  });
};

export const { wrap: sentryWrap } = Sentry.Native;

I am trying to test the above crash-reporting module like so:

crash-reporting.test.ts

import * as Sentry from 'sentry-expo';

import { initialiseCrashReporting } from './crash-reporting';

jest.mock('sentry-expo', () => {
  const originalModule = jest.requireActual('sentry-expo');

  return {
    ...originalModule,
    init: jest.fn(),
  };
});

describe('Crash Reporting Test Suite', () => {
  it('should initialise sentry', () => {
    const initSpy = jest.spyOn(Sentry, 'init');

    initialiseCrashReporting();

    expect(initSpy).toHaveBeenCalled();
  });
});

Even though initialiseCrashReporting gets called, spyOn never catches the event where init gets called.

I realised that the globally mocked sentry-expo never gets overridden with the one in the crash-reporting.test.ts file.

I have 2 below-given questions related to this problem:

  1. How can I override the globally mocked modules? Or how can I be assured that by calling initialiseCrashReporting, I am initialising sentry?
  2. Can we override global beforeall for specific test cases?

Thanks in anticipation!

shet_tayyy
  • 5,366
  • 11
  • 44
  • 82

0 Answers0