在jest测试期间未定义NativeModules.SettingsManager

wgx48brx  于 2023-08-01  发布在  Jest
关注(0)|答案(1)|浏览(166)

我是一个测试react-native项目的新手,但通常我理解mocking的概念。在一个新的测试中,由于“全局”应用程序提供商的原因,需要进行大量的设置,其中一个设置在我的测试中抛出了一个错误:

TypeError: Cannot read properties of undefined (reading 'settings')

字符串
堆栈跟踪转到:

onst deviceLocale: Locales =
    Platform.OS === 'ios'
      ? NativeModules.SettingsManager.settings.AppleLocale ||
        NativeModules.SettingsManager.settings.AppleLanguages[0]
      : NativeModules.I18nManager.localeIdentifier;


这意味着在NativeModules导入中没有SettingsManagerimport { NativeModules, Platform } from 'react-native';
我已经尝试了很多方法来模拟react-native,但这也有它自己的问题。我不想让SettingsManager成为可选链接,因为没有理由这样做。
我是否应该更改我的配置/设置文件?这是一个受管理的世博会工作流程。
Jest配置:

module.exports = {
  preset: 'jest-expo',
  setupFilesAfterEnv: [
    '<rootDir>/src/test-utils/jest-setup.ts',
    '@testing-library/jest-native/extend-expect',
  ],
  collectCoverage: false,
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
  },
  transformIgnorePatterns: [
    'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg|@rneui/.*|@fluidtruck/.*|@expo/.*)',
  ],
};


会不会是我的transformIgnorePatterns
我的jest.setup文件是:

import 'cross-fetch/polyfill';
import '@testing-library/jest-native/extend-expect';

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import { NativeModules } from 'react-native';

import { en } from '@/locales/en';
import { es } from '@/locales/es';

import { server } from '../mocks/server';

const resources = {
  en,
  es,
};

beforeAll(() => {
  server.listen();

  jest.mock('react-i18next', () => ({
    useTranslation: () => {
      return {
        t: (str: string) => str,
        i18n: {
          changeLanguage: () => new Promise(jest.fn),
        },
      };
    },
  }));

  i18n.use(initReactI18next).init({
    lng: 'en',
    defaultNS: 'common',
    debug: false,
    resources,
  });

  jest.mock('@react-navigation/core', () => {
    const actualNav = jest.requireActual('@react-navigation/core');
    return {
      ...actualNav,
      useNavigation: () => ({
        navigate: jest.fn(),
        dispatch: jest.fn(),
        goBack: jest.fn(),
      }),
      useRoute: () => ({
        params: jest.fn(),
      }),
    };
  });
});

jest.mock('@react-navigation/native');

jest.mock('@react-native-async-storage/async-storage', () =>
  require('@react-native-async-storage/async-storage/jest/async-storage-mock')
);

afterEach(() => server.resetHandlers());

afterAll(() => server.close());


我试着加了这个模拟,

jest.mock('react-native', () => {
    const actual = jest.requireActual('react-native');
    return {
      ...actual,
      NativeModules: jest.fn(),
    };
  });


但它导致了太多的警告沿着这条线:
PushNotificationIOS已从react-native核心中提取,并将在未来版本中删除。它现在可以从'@react-native-community/push-notification-ios'而不是'react-native'安装和导入。参见https://github.com/react-native-push-notification-ios/push-notification-ios
而我的实际测试文件,我试图在提供者钩子中测试一个方法,我甚至还没有能够做到这一点:

import { act, renderHook } from '@testing-library/react-hooks';
import React, { ReactNode } from 'react';

import { Wrapper } from '@/src/test-utils/wrapper';

import { VehicleDataProvider } from '../../../Vehicle';
import { InspectionData } from '../../InspectionsDataProvider/__fixtures__/inspection.fixture';
import { InspectionsDataProvider } from '../../InspectionsDataProvider/InspectionsDataProvider';
import { ActiveInspectionProvider } from '../ActiveInspectionProvider';
import { useActiveInspectionContext } from '../useActiveInspectionContext';

describe('useActiveInspectionProvider', () => {
  test('#handleNextPress sends expected payload', async () => {
    jest.mock('@react-navigation/native', () => ({
      ...jest.requireActual('@react-navigation/native'),
      useRoute: () => ({
        params: {
          aggId: '',
          section: '0eafdffc-8ba5-45b6-ada8-9372dabe81c2',
          step: '1e46bdf9-a30a-4d41-bc61-a39b0a86d2f3',
          name: 'Dev 1',
          vehicleId: '26284',
        },
      }),
    }));

    const wrapper = ({ children }: { children: ReactNode }) => {
      console.log({ children });

      return (
        <Wrapper>
          <VehicleDataProvider>
            <InspectionsDataProvider>
              <ActiveInspectionProvider>{children}</ActiveInspectionProvider>
            </InspectionsDataProvider>
          </VehicleDataProvider>
        </Wrapper>
      );
    };

    const { result, waitForNextUpdate } = renderHook(() => useActiveInspectionContext(), {
      wrapper,
    });

    act(() => {
      if (!InspectionData.formGroups[1].formFields[0].formFieldOptions) {
        throw new Error('Missing FormField options data');
      }
      console.log(result.current);

      result.current.handleNextPress({
        [InspectionData.formGroups[1].formFields[0].uuid]:
          InspectionData.formGroups[1].formFields[0].formFieldOptions[1].value,
      });
    });

    await waitForNextUpdate();

    expect(fetch as jest.Mock).toHaveBeenLastCalledWith();
  });
});


我使用的版本:“jest”:“^27.4.7”,“jest-expo”:“^44.0.1”,“react-native”:“0.69.6”,“expo”:“~46.0.19”,
我可以用jest对NativeModules做什么?

f45qwnt8

f45qwnt81#

你需要在React-native中模拟Native模块。试试这个:

jest.mock('react-native', () => {
  const RN = jest.requireActual('react-native');

  RN.NativeModules.SettingsManager = {
    settings: {
      AppleLocale: 'en-US',
      AppleLanguages: ['fr-FR', 'en-US'],
    },
  };
  return RN;
});

字符串

相关问题