使用 Jest 模拟 @apollo/react-hooks useQuery

Posted

技术标签:

【中文标题】使用 Jest 模拟 @apollo/react-hooks useQuery【英文标题】:Mock @apollo/react-hooks useQuery using Jest 【发布时间】:2020-10-30 23:53:13 【问题描述】:

我目前正在尝试从 index.ts 模拟 useQuery,但是我不能这样做,因为 useMenu 是一个只读值。

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

我尝试关注the documentation,但实际上我无法实现这一点,因为我没有返回任何 html,只是返回结果。

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

您可以模拟@apollo/react-hooks 模块。

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

如果您还需要模拟其他方法(如fetchMoreuseMutation),或者直接模拟通过client.query 执行的查询,您也可以这样做。 This post 有更多关于模拟它们的细节。

【讨论】:

为我节省了很多时间和心痛。谢谢。【参考方案2】:

jest.mock('@apollo/react-hooks, () => ) 如果您的目标组件只有一个查询,则非常好。但是,如果您根据不同的条件左右对一个组件进行多个查询。您需要考虑使用来自 apollo 官方文档的 MockedProvider。

【讨论】:

【参考方案3】:

通过这种方法,您可以使用 jest.mock() 将不同的模拟数据返回到您的多个测试中。

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

【讨论】:

以上是关于使用 Jest 模拟 @apollo/react-hooks useQuery的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 中测试 readFragment?

如何使用 jest.fn() 在 jest 中使用 typescript 模拟函数

如何使用 jest.fn() 模拟属性

Jest 手动模拟在 CRA 中不使用模拟文件

使用 jest.mock('axios') 时如何模拟拦截器?

如何使用 Jest 模拟异步函数