Skip to content

Refactor test to minimally depende on JS SDK internals #3572

Description

@krystofwoldrich

Description

Currently, we use a lot of mocked classes and we depend on the internal structure of the JS SDK, this leads to several tests breaking when we upgrade to a newer JS SDK.

  • This should not happen unintentionally, if the test intention was to test RN SDK implementation it should not depend on JS internals.

  • In cases where the JS SDK internal is crucial to RN SDK and its change would break RN we should add a separate test.

Example of tests to change:

  • Should not mock the Hub and Scope
    const getMockScope = () => {
    let scopeTransaction: unknown;
    let scopeUser: User | undefined;
    return {
    getTransaction: () => scopeTransaction,
    setSpan: jest.fn((span: unknown) => {
    scopeTransaction = span;
    }),
    setTag(_tag: unknown) {
    // Placeholder
    },
    setContext(_context: unknown) {
    // Placeholder
    },
    addBreadcrumb(_breadcrumb: unknown) {
    // Placeholder
    },
    getUser: () => scopeUser,
    };
    };
    const mockAddBreadcrumb = jest.fn();
    const getMockHub = () => {
    const mockHub = new Hub(new BrowserClient({ tracesSampleRate: 1 } as BrowserClientOptions));
    const mockScope = getMockScope();
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    mockHub.getScope = () => mockScope as any;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    mockHub.configureScope = jest.fn(callback => callback(mockScope as any));
    mockHub.addBreadcrumb = mockAddBreadcrumb;
    return mockHub;
    };
    interface MockGesture {
    handlers?: {
  • The same
    const getMockScope = () => {
    let scopeTransaction: Transaction | undefined;
    let scopeUser: User | undefined;
    return {
    getTransaction: () => scopeTransaction,
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    setSpan: jest.fn((span: any) => {
    scopeTransaction = span;
    }),
    setTag(_tag: any) {
    // Placeholder
    },
    setContext(_context: any) {
    // Placeholder
    },
    addBreadcrumb(_breadcrumb: any) {
    // Placeholder
    },
    getUser: () => scopeUser,
    };
    };
    const getMockHub = () => {
    const mockHub = new Hub(
    new BrowserClient({
    tracesSampleRate: 1,
    integrations: [],
    transport: () => ({
    send: jest.fn(),
    flush: jest.fn(),
    }),
    stackParser: () => [],
    }),
    );
    const mockScope = getMockScope();
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    mockHub.getScope = () => mockScope as any;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    mockHub.configureScope = jest.fn(callback => callback(mockScope as any));
    return mockHub;
    };
    import type { Event, Scope } from '@sentry/types';
    import type { AppState, AppStateStatus } from 'react-native';

Activity

  1. antonis commented on Jun 9, 2026

    @antonis
    Contributor

    The original problem — heavy Hub/Scope class mocking that broke on JS SDK upgrades — was resolved as part of the JS SDK v8 migration:

    There are still a handful of test files that do full jest.mock('@sentry/core', ...) replacements without jest.requireActual (e.g. NavigationContainer.test.tsx, NativeLogListener.test.ts, FeedbackForm.test.tsx, collectModules.test.ts), which could break on JS SDK upgrades. These can be addressed incrementally as we touch those files — no dedicated effort needed.

    Closing as the core issue is resolved.

  2. self-assigned this
    on Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions