Почему jest не вызывает функцию, которая находится внутри хука useEffect? - PullRequest
0 голосов
/ 15 марта 2020

У меня есть асин c функция setInitialData, которая вызывается в useEffect хуке в приложениях provider. Я хочу проверить, что функция была вызвана. Этот тест не пройден. Почему?

const dispatch = jest.fn();
const state = {...}
jest.mock('../context/actions', () => ({
  setInitialData: jest.fn(),
}));

test('setInitialData fn is called in useEffect hook in the provider', () => {
  const {debug} = render(<CurrencyExchange />, {state, dispatch});
  expect(setInitialData).toHaveBeenCalled();
});


Expected number of calls: >= 1
Received number of calls:    0

Просто чтобы дать немного больше контекста, у меня есть пользовательская функция render, поэтому мой компонент находится в провайдере:

const customRender = (ui, {state = {}, dispatch = () => undefined, ...options} = {}) => {
  function Wrapper({children, props}) {
    return (
      <CurrencyStateContext.Provider value={state} {...props}>
        <CurrencyDispatchContext.Provider value={dispatch}>
          <ThemeProvider theme={theme}>
            <CSSReset />
            {children}
          </ThemeProvider>
        </CurrencyDispatchContext.Provider>
      </CurrencyStateContext.Provider>
    );
  }
  return render(ui, {wrapper: Wrapper, ...options});
};
export {customRender as render};

И фактическая реализация провайдера выглядит следующим образом это:

function CurrencyProvider({children}: CurrencyProviderProps): JSX.Element {
  const [state, dispatch] = React.useReducer<React.Reducer<CurrencyState, Action>>(reducer, initialState);

  React.useEffect(() => {
    setInitialData(dispatch);
  }, []);

--- РЕДАКТИРОВАТЬ ---

ОК. Я имею.

  React.useEffect(() => {
    setInitialData(dispatch);
  }, []);

In перемещен в CurrencyExchange компонент, и теперь я получаю ожидаемые утверждения. Но все же, кто-нибудь может объяснить мне, почему setInitialData не вызывается, когда он находится непосредственно в поставщике приложений?

1 Ответ

0 голосов
/ 15 марта 2020

useEffect является асинхронным, поэтому вы должны ждать его, используя act. useLayoutEffect синхронно

в ожидании useEffect вы можете попробовать это

import { act } from 'react-dom/test-utils'

test('setInitialData fn is called in useEffect hook in the provider', () => {
  let debug
  await act(async () => { 
    debug = render(<CurrencyExchange />, {state, dispatch}).debug;
  })

  expect(setInitialData).toHaveBeenCalled();
});


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...