4

这是我使用 MockedProvider 的方式。如何在 mocks 数组中模拟 refetch?

const mocks = [{
        request: {
            query: GET_USERS_BY_FACILITY,
            variables: {
                facility: 300
            }
        },
        result: {
            data: {
                GetUsersByFacility: [{
                    nuId: 'Q916983',
                    userName: faker.internet.userName(),
                    profileKey: 'testKey',
                    profileValue: 'testValue',
                    __typename: 'FacilityUser'
                }]
            }
        },
        refetch: () => {
            return {
                data: {
                    GetUsersByFacility: [{
                        nuId: 'Q916983',
                        userName: faker.internet.userName(),
                        profileKey: 'testKey',
                        profileValue: 'testValue',
                        __typename: 'FacilityUser'
                    }]
                }
            }
        }
    }

此测试用例在触发删除事件时调用 refetch 函数。

 it('should be able to click on delete user', async () => {
        const {getByTestId} = render(
            <MockedProvider mocks={mocks}>
                <Users selectedFacility={300}/>
            </MockedProvider>)

        await wait(0)
        fireEvent.click(getByTestId('btnDelete'))
    })

我一直在尝试不同的方法,似乎没有一个有效。我收到错误消息TypeError: Cannot read property 'refetch' of undefined

非常感谢,希望得到答复。

问候,--拉贾尼

4

4 回答 4

3

对于可能仍然遇到此问题的任何人,在您的测试中重新获取工作的解决方案是使用该newData方法,同时跟踪已调用的查询。

我不知道这是否是 MockedProvider 实现中的一个错误,但我正试图newData与.resultnewDataresult

一个可行的解决方案(使用 useQuery 和 Apollo Client 3 测试)是这样的:

let queryCalled = false;
const refetchMock = {
  request: {
    query: YOUR_QUERY
  },
  newData: () => {
    if (queryCalled) {
      return { 
        data: {
          // your refetched data
        }
      }; 
    } else {
      queryCalled = true;
      return { 
        data: {
          // your first fetched data
        } 
      }; 
    }
  }
};
于 2020-11-30T15:51:27.497 回答
2

也许现在回答有点晚,但如果你还没有得到任何答案,你会参考我解决的方式。

请注意,这可能不是正确的答案。


const mocks = [
  {
    request: {
      query: GET_DOG_QUERY,
      variables: {
        name: 'Buck',
      },
    },
    result: () => {
      // do something, such as recording that this function has been called
      // ...
      return {
        data: {
          dog: { id: '1', name: 'Buck', breed: 'bulldog' },
        },
      }
    },
  },
];
  • 我根据这个短语制作了我的重新获取测试代码// do something, such as recording that this function has been called

这是我的模拟示例。

let queryCalled = false

const testingData = (value) => ({
  data: {....}
})

const TESTING_MOCK = {
  request: {
    query: TESTING_QUERY,
    variables: { some: "variables" },
  },
  result: () => {
    if (queryCalled) return testingData("refetched");
    else {
      queryCalled = true;
      return testingData("first fetched");
    }
  },
};
  • 单击按钮时,此组件会重新获取数据。我按这个顺序设计了我的测试代码
    1. 第一次渲染时,它会获取模拟数据。
      => 在上面的代码queryCalledfalse,它重新赋值queryCalledtrue并返回“第一次获取”的模拟数据,
    2. 当点击事件发生时,也会发生重新获取。
      => 基于相同的原则,模拟数据返回“重新获取”模拟数据。

我的测试代码示例在这里

it("refetch when clicked save button.", async () => {
  const mocks = [TESTING_MOCK];
  let utils: RenderResult = render(<SomeTestingComponent mocks={mocks} />);

  await waitForNextTick(); //for getting a data, not loading

  const titleInput = utils.getByDisplayValue("first fetched");

  const saveBtn = utils.getByText("save");
  fireEvent.click(saveBtn);
  await waitForElement(() => utils.getByDisplayValue("refetched"));
})

如果您有任何其他建议,请告诉我!

于 2020-01-21T05:44:26.983 回答
1

newData解决方案不适用于 apollo client @2.6

作为一种解决方法,对于使用的少数测试,refetch我必须物理模拟该useQuery函数并提供模拟函数以返回refetch; 对于我们的自定义钩子(其中一个被覆盖的useQuery钩子被导出为default),它看起来像这样:

import * as useQueryModule from '~/hooks/useQuery';

describe('test the thing', () => {
    let useQuerySpy;

    beforeEach(() => {
        // Spy on the `useQuery` function so we can optionally provide alternate behaviour.
        useQuerySpy = jest.spyOn(useQueryModule, 'default');
    })

    afterEach(() => {
      // Restore any mocked behaviour
      useQuerySpy.mockRestore();
    });

    it('does a thing', async () => {
        const refetchedApolloResponse = buildResponse(refetchData) // some function to build the shape / data of apollo response
        const initialApolloResponse = buildResponse(initialData) // some function to build the shape / data of apollo response
     
       const mockRefetch = jest.fn().mockResolvedValue({ data: refetchedApolloResponse });
       useQuerySpy.mockReturnValue({ data: initialApolloResponse, refetch: mockRefetch });

      // Assert stuff
    }
})

于 2020-11-05T13:57:46.040 回答
0

该解决方案对我不起作用,并且不确定它是否会起作用,因为它在我的情况下不起作用。

let queryCalled = false

const testingData = (value) => ({
  data: {....}
})

const TESTING_MOCK = {
  request: {
    query: TESTING_QUERY,
    variables: { some: "variables" },
  },
  result: () => {
    if (queryCalled) return testingData("refetched");
    else {
      queryCalled = true;
      return testingData("first fetched");
    }
  },
};

所以我通过另一种方式解决了它:

const mocks = [
  {
    request: {
      query: GET_DOG_QUERY,
      variables: {
        name: 'Buck',
      },
    },
    result: {
      data: {
        dog: { id: '1', name: 'Buck', breed: 'bulldog' },
      },
    },
    newData: jest.fn(() => ({
      data: {
        dog: { id: '1', name: 'Refetched-Buck', breed: 'refetched-bulldog' },
      },
    })),
  },
];

它对我来说就像一个魅力。

于 2020-02-24T16:22:17.573 回答