Search code examples
javascriptreactjsjestjsapollo-client

Why is client.query not being called in my jest test?


mocking the apollo hook

jest.mock("@apollo/client", () => ({
  ...jest.requireActual("@apollo/client"),
  useApolloClient: () => ({
    query: jest.fn().mockResolvedValueOnce({
      data: { myReturnValue: { some: "data" } },
      loading: false,
      errors: undefined,
    }),
  }),
}))

my function

  const myFunction = (input) => {
    console.log("called this?") // this 100% gets called in the test
    const data = { ...defaultData, ...input }

    return client
      .query({
        query: Query,
        fetchPolicy: "network-only",
        variables: {},
      })
      .then(({ data, errors }) => {
        if (!data?) {
          alert(errors)
        } else {
          console.log("in else block") // this 100% gets called in the test
          runFunction()
        }
      })
  }

in my test it is logging: "in else block"

and in my test I have:

fireEvent.click(screen.getByText("My Button Text"))
await waitFor(() => expect(useApolloClient().query).toBeCalledTimes(1))

In the test output I get

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

why is this? It definitely called client.query as it got in the logs


Solution

  • As @phry said, don't mock @apollo/client module. Instead, follow the Testing React components guide.

    Standing from the perspective of the user to test the component, which is equivalent to the black box test. Do not test the specific implementation(such as expect(someMethod).toBeCalled()). Instead, we should assert what the component renders. After the user interacts with the component, what changes the rendering content will be

    e.g.

    index.tsx:

    import React, { useState } from 'react';
    import { gql, useApolloClient } from '@apollo/client';
    
    export const GET_DOG_QUERY = gql`
      query GetDog($name: String) {
        dog(name: $name) {
          id
          name
          breed
        }
      }
    `;
    
    export function SomeComponent() {
      const client = useApolloClient();
    
      const [data, setData] = useState();
      console.log("🚀 ~ SomeComponent ~ data:", data)
    
      const onClick = () => {
        client
          .query({
            query: GET_DOG_QUERY,
            fetchPolicy: 'network-only',
            variables: {
              name: 'Buck',
            },
          })
          .then(({ data, errors }) => {
            setData(data);
          });
      };
    
      return (
        <div>
          <button onClick={onClick}>My Button Text</button>
          {data && <span>{data.dog.breed}</span>}
        </div>
      );
    }
    

    index.test.tsx:

    import React from 'react';
    import { MockedProvider } from '@apollo/client/testing';
    import { GET_DOG_QUERY, SomeComponent } from '.';
    import { fireEvent, render, screen } from '@testing-library/react';
    import '@testing-library/jest-dom';
    
    describe('78333569', () => {
      test('should pass', async () => {
        const mocks = [
          {
            request: {
              query: GET_DOG_QUERY,
              variables: {
                name: 'Buck',
              },
            },
            result: {
              data: {
                dog: { id: '1', name: 'Buck', breed: 'bulldog' },
              },
            },
          },
        ];
    
        render(
          <MockedProvider mocks={mocks} addTypename={false}>
            <SomeComponent />
          </MockedProvider>,
        );
    
        fireEvent.click(screen.getByText('My Button Text'));
        expect(await screen.findByText('bulldog')).toBeInTheDocument();
      });
    });
    

    Test result:

    
      console.log
        🚀 ~ SomeComponent ~ data: undefined
    
          at log (stackoverflow/78333569/index.tsx:18:11)
    
      console.log
        🚀 ~ SomeComponent ~ data: { dog: { id: '1', name: 'Buck', breed: 'bulldog' } }
    
          at log (stackoverflow/78333569/index.tsx:18:11)
    
     PASS  stackoverflow/78333569/index.test.tsx
      78333569
        √ should pass (78 ms)                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                         
    Test Suites: 1 passed, 1 total                                                                                                                                                                                                                       
    Tests:       1 passed, 1 total                                                                                                                                                                                                                       
    Snapshots:   0 total
    Time:        1.332 s, estimated 3 s
    Ran all test suites related to changed files.
    

    package versions:

    "@apollo/client": "^3.9.11"