首页 > 解决方案 > react-query 如何在 Jest 测试中从自定义 useMutation 挂钩调用 mutate

问题描述

我正在运行一个 React Native 项目,我正在测试用 react-query 编写的自定义钩子。我正在使用 Jest、@testing-library/react-hooks 和 @testing-library/react-native。在我的测试中,我似乎找不到调用钩子返回的 mutate 函数的方法。

下面看一下自定义钩子:

export default function useAuthentication() {
  const { mutate, data, isSuccess, isError } = useMutation(
    authenticationApi.authenticateUser
  );
  return { mutate, data, isSuccess, isError };
}

根据 react-query 的文档,我正在使用 renderHook() 渲染钩子并等待突变调用的结果:

const authBody: AuthBody = {
  username: '111111',
  password: '111111',
};

describe('Authentication Hook', () => {
  const sanityCall = () =>
    axios.post('http://localhost:4000/auth/authenticate');
  console.log(sanityCall());

  const queryClient = new QueryClient();
  it('Gets authentication data', async () => {
    const wrapper = ({ children }: any) => (
      <QueryClientProvider client={queryClient}>
        <Provider store={store}>
          <PersistGate loading={null} persistor={persistor}>
            {children}
          </PersistGate>
        </Provider>
      </QueryClientProvider>
    );
    const { result, waitFor } = renderHook(() => useAuthentication(), {
      wrapper,
    });

    await waitFor(() => {
      result.current.mutate({
        username: authBody.username,
        password: authBody.password,
      });
      return result.current.isSuccess;
    });
    expect(result.current.data).toEqual({ answer: 42 });
  });
});

它不调用 API。我的本地服务器的终端窗口记录了我在使用时正在 ping 服务器,sanityCall()但在我注释掉该调用并依赖钩子时保持沉默。有没有人对如何测试这样的自定义钩子有任何想法?

标签: react-nativejestjsreact-hooksreact-queryreact-native-testing-library

解决方案


将其包装在 Act 中并在那里调用 mutate 导致调用我的服务器:

const Wrapper = ({ children }: any) => (
  <QueryClientProvider client={queryClient}>
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <NavigationContainer>{children}</NavigationContainer>
      </PersistGate>
    </Provider>
  </QueryClientProvider>
);

it('Gets authentication data', async () => {
    const { result } = renderHook(() => useAuthentication(), {
      wrapper: Wrapper,
    });
    act(() => {
      result.current.mutate({
        username: authBody.username,
        password: authBody.password,
      });
    });
    const token = store.getState().token;
    console.log('TOKEN:');
    console.log(token);
  });

推荐阅读