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:
- How can I override the globally mocked modules? Or how can I be assured that by calling initialiseCrashReporting, I am initialising sentry?
- Can we override global beforeallfor specific test cases?
Thanks in anticipation!
