Jest Redux Persist: TypeError: невозможно прочитать свойство 'catch' неопределенного значения в writeStagedState

Я пытаюсь протестировать свой LoginScreen с помощью Jest и Typescript. Я использую redux и redux-persist для хранения и настроил хранилище для использования AsyncStorage как части конфигурации. Я подозреваю, что redux-persist пытается регидратировать после того, как встроенная функция тайм-аута, которую он использует, исчерпывается, и пытается установить хранилище по умолчанию? Я получаю следующую ошибку:

console.error
redux-persist: rehydrate for "root" called after timeout. undefined
undefined
at _rehydrate (node_modules/redux-persist/lib/persistReducer.js:70:71)
at node_modules/redux-persist/lib/persistReducer.js:102:11
at tryCallOne (node_modules/promise/setimmediate/core.js:37:12)
at Immediate._onImmediate (node_modules/promise/setimmediate/core.js:123:15)

Сейчас мой тест выглядит так:

describe('Testing LoginScreen', () => {
  it('should render correctly', async () => {
    const { toJSON } = render(<MockedNavigator component={LoginScreen} />);
    await act(async () => await flushMicrotasksQueue());
    expect(toJSON()).toMatchSnapshot();
  });
});

а мой MockNavigator выглядит так:

type MockedNavigatorProps = {
  component: React.ComponentType<any>;
  params?: {};
};

const Stack = createStackNavigator();
const MockedNavigator = (props: MockedNavigatorProps) => {
  return (
    <MockedStorage>
      <NavigationContainer>
        <Stack.Navigator>
          <Stack.Screen
            name='MockedScreen'
            component={props.component}
            initialParams={props.params}
          />
        </Stack.Navigator>
      </NavigationContainer>
    </MockedStorage>
  );
};

export default MockedNavigator;

Вот как я создаю свое хранилище:

import 'react-native-gesture-handler';
import * as React from 'react';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from '../src/AppState/store';

type MockedStorageProps = {
  children: any;
};

const MockedStorage = (props: MockedStorageProps) => {
  return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        {props.children}
      </PersistGate>
    </Provider>
  );
};

export default MockedStorage;

2 ответа

Я решил эту же ошибку, используя этот совет из проблемы на redux-persistрепозиторий: https://github.com/rt2zz/redux-persist/issues/1243#issuecomment-692609748.

(Это также имело побочный эффект, заключающийся в предотвращении ошибок регистрации в тесте из redux-logger.)

      jest.mock('redux-persist', () => {
  const real = jest.requireActual('redux-persist');
  return {
    ...real,
    persistReducer: jest
      .fn()
      .mockImplementation((config, reducers) => reducers),
  };
});

@алексбразиер:

По сути, он просто обходит redux-persist, возвращая редукторы напрямую, не оборачивая их в redux-persist.

Решение LordParsley мне не помогло. (вызвал тайм-аут тестов), но направил меня на правильный путь. Добавляю это в свойjest.setup.jsрешил мою ошибку:

      jest.mock('@react-native-async-storage/async-storage', () => {
  return {
    getItem: async (...args) => args,
    setItem: async (...args) => args,
    removeItem: async (...args) => args,
  };
});

Решение пришло из этого обсуждения: https://github.com/react-native-async-storage/async-storage/issues/379, они также предлагают скопировать макеты, но у меня это не сработало.

ОБНОВЛЕНИЕ : коллеге не понравилось решение, и он предпочел это: чтобы вы издевались только над функцией, вызывающей ошибку, и оставляли все остальные ошибки, как в исходном макете, добавьте следующее в файл макета для асинхронного хранилища, а не jest.setup и обратитесь к нему в своемjest.config:

      import asyncStorageMock from '@react-native-async-storage/async-storage/jest/async-storage-mock';

const originalSetItemMock = asyncStorageMock.setItem.bind(asyncStorageMock);
asyncStorageMock.setItem = function newSetItemMock() {
    // Types falsely assert that the below mock function returns a promise, so we ignore the return value.
    originalSetItemMock(...arguments);
    return Promise.resolve();
};
export default asyncStorageMock;
Другие вопросы по тегам