Search code examples
react-nativejestjsreact-hooksreact-queryreact-native-testing-library

react-query how to call mutate from custom useMutation hook in Jest test


I'm running a React Native project where I'm testing custom hooks written with react-query. I'm using Jest, @testing-library/react-hooks and @testing-library/react-native. In my testing I can't seem to find a way to call the mutate function returned by the hook.

Here's a look at the custom hook:

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

Following the documentation from react-query I am rendering the hook with renderHook() and awaiting the result of the mutation call:

    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 });
      });
    });

It doesn't call the API. My local server's terminal window logs that I'm pinging the server when using the sanityCall() but remains silent when I comment out that call and rely on the hook. Does anyone have any ideas for how to go about testing a custom hook like this?


Solution

  • Wrapping it in Act and calling mutate there resulted in a call to my server:

    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);
    });