Duarte Castanho
Duarte Castanho

Reputation: 315

Mock @apollo/react-hooks useQuery using Jest

I'm currently trying to mock the useQuery from index.ts, however I cannot do it as the useMenu is a readonly value.

index.ts

import { useQuery } from "@apollo/react-hooks";
import { MENU } from "../../graphql/queries/menu";

export const useMenu = (myNumber: number) => {
  return useQuery(MENU, {
    variables: { myNumber }
  });
};

menu.ts

import gql from "graphql-tag";

export const MENU = gql`
  fragment MenuItemFields on MenuItem {
    field1
    field2
    field3
    field4
  }
  query Menu($myNumber: Float!) {
    menu(myNumber: $myNumber) {
      items {
        ...MenuItemFields
        items {
          ...MenuItemFields
          items {
            ...MenuItemFields
            items {
              ...MenuItemFields
            }
          }
        }
      }
    }
  }
`;

menu.test.ts

import { useQuery } from '@apollo/react-hooks';
import {httpResponse as mockMenuAPIString} from '../../../../../mocks/expectations/Storm-Hub-Menu/storm-hub-menu.json';
import {getEligibleMenuEntries} from '../../../../server/modules/graphql/utils';
import {useMenu} from '../../services/menu'

it('returns valid Menu', () => {
    // Convert mockMenuAPI to mockMenu

    const mockMenuAPI = JSON.parse(mockMenuAPIString.body);
    const mockMenu = getEligibleMenuEntries(mockMenuAPI);      //Working

    ... How do I mock the useQuery?
    
    const res = useMenu(10000);

    expect(res).toEqual(mockMenu);
});

I've tried to follow the documentation but i couldn't actually implement this since I'm not returning any HTML, just the result.

In the example

Any help would be appreciated.

Upvotes: 5

Views: 18268

Answers (3)

freemany
freemany

Reputation: 11

With this approach, you can use jest.mock() with different mock data return to your multiple tests.

let mockData; // You have use mock as prefix in your data for lazy load !important!
jest.mock('@ts-gql/apollo', () => {
  return {
    __esModule: true,
    useQuery: jest.fn(() => mockData),
  };
});

describe("My feature", () => {
  it("should have foo", () => {
    mockData = { data: 'foo' };
    renderComponent();
    expect(something).toBe('foo');
  });
  
  it("should have bar", () => {
    mockData = { data: 'bar' };
    renderComponent();
    expect(something).toBe('bar');
  });
});

Upvotes: 1

qmkiwi
qmkiwi

Reputation: 135

jest.mock('@apollo/react-hooks, () => {}) is pretty good if your target component has only one query. But if you have multiple queries for one component based on different conditions or so. You need to considering use the MockedProvider from apollo official doc.

Upvotes: 0

Pulkit Goyal
Pulkit Goyal

Reputation: 5654

You can mock the @apollo/react-hooks module.

jest.mock('@apollo/react-hooks', () => {
  
  const data = { menu }; // put your mock data here
  return {
    __esModule: true,
    useQuery: jest.fn(() => ({ data })),
  };
});

If you need to mock other methods too (like fetchMore, useMutation), or directly mock queries performed through client.query, you can do that too. This post has some more details about mocking each one of them.

Upvotes: 13

Related Questions