Apollo 客户端 MockedProvider:跳过加载状态

Jef*_*che 5 typescript apollo react-apollo apollo-client

我使用 Apollo 设置了一个 React 应用程序,以拥有一个处理从网络加载数据的包装器组件,以便下面的每个组件都可以直接从 Apollo 缓存查询数据,而不必担心处理加载状态。因此,我的组件如下所示:

export const COUNT_OFF_ADAPTER_QUERY = gql`
  query CountOffAdapterQuery($vampId: ID!) {
    vamp(id: $vampId) @client {
      id
      countingOff
      countingOffStartTime
    }
  }
`;

export const CountOffAdapter: React.FC<{}> = () => {
  const vampId = useCurrentVampId();

  const {
    data: {
      vamp: { countingOff, countingOffStartTime }
    }
  } = useQuery<CountOffAdapterQuery>(COUNT_OFF_ADAPTER_QUERY, {
    variables: { vampId }
  });

  const prev = usePrevious({ countingOff, countingOffStartTime });

  const countOff = useCountOff();

  useEffect(() => {
    // Do react stuff
  }, [countOff, countingOff, prev]);

  return null;
};
Run Code Online (Sandbox Code Playgroud)

在实践中(在浏览器中),这非常有效,因为在应用程序中 Apollo 会立即从缓存返回数据,因此loading调用的结果useQuery永远不会true,我可以解构数据,在后续挂钩中使用它等。

然而,当需要测试时,似乎MockedProvider 必然返回loadingtrue,测试编写者无法控制是否跳过该状态(显然我希望这样做)。请注意,当useQuery返回loading到 be时true,渲染我的组件将出错,因为它正在解构data,这是未定义的。因此,我永远无法在测试失败的情况下超过该加载状态。

这是我的测试代码:

it("works", async () => {
  (useCurrentVampId as jest.Mock).mockImplementation(
    () => "6070dedd58d7bf715eb2a6c5"
  );
  const component = mount(
    <MockedProvider
      mocks={[
        {
          request: {
            query: COUNT_OFF_ADAPTER_QUERY,
            variables: {
              vampId: "6070dedd58d7bf715eb2a6c5"
            }
          },
          result: {
            data: {
              vamp: {
                id: "6070dedd58d7bf715eb2a6c5",
                countingOff: true,
                countingOffStartTime: 1234
              }
            }
          }
        }
      ]}
      addTypename={false}
    >
      <CountOffAdapter></CountOffAdapter>
    </MockedProvider>
  );
  await wait(0);
  component.update();
});
Run Code Online (Sandbox Code Playgroud)

我很好奇是否有办法解决这个问题。如果您可以在查询模拟中指定,那就太好了loading: false,但您不能。

Bla*_*rov 1

我正在使用Next.js,并且主要进行服务器端渲染,因此我遇到了与您相同的情况,我决定进一步调查一下。看起来 apollo-client 在实际的模拟中提供了延迟属性,例如:

const mock: MockedResponse = {
  request: {
    query: SomeDocument,
    variables: { slug: 'test' },
  },
  result: { data: fakeData },
  delay: 0, // <---------THIS ----------|(number or undefined)
};
Run Code Online (Sandbox Code Playgroud)

但这也没有帮助,所以我更深入地研究了源代码,当我看到以下内容后,一切都变得清晰起来:

const mock: MockedResponse = {
  request: {
    query: SomeDocument,
    variables: { slug: 'test' },
  },
  result: { data: fakeData },
  delay: 0, // <---------THIS ----------|(number or undefined)
};
Run Code Online (Sandbox Code Playgroud)

正如您在这里所看到的,延迟仅用作 setTimeout 的毫秒参数,这是一个异步代码 -> 意味着将在 javascript 队列中的同步代码之后添加https://developer.mozilla.org/en -US/docs/Web/JavaScript/Event_loop)。因此,为延迟字段提供什么值并不重要。

您问题的最终结论:目前无法跳过加载状态。