【问题标题】:Apollo MockedProvider not returning expected dataApollo MockedProvider 未返回预期数据
【发布时间】:2021-02-16 12:49:41
【问题描述】:

我写了一个调用 apollo useQuery 的钩子。很简单:

使用决策者:

import { useState } from 'react';
import { useQuery, gql } from '@apollo/client';

export const GET_DECIDER = gql`
  query GetDecider($name: [String]!) {
    deciders(names: $name) {
      decision
      name
      value
    }
  }
`;

export const useDecider = name => {
  const [enabled, setEnabled] = useState(false);

  useQuery(GET_DECIDER, {
    variables: {
      name
    },
    onCompleted: data => {
      const decision = data?.deciders[0]?.decision;
      setEnabled(decision);
    },

    onError: error => {
      return error;
    }
  });

  return {
    enabled
  };
};

我现在正在尝试测试它,MockedProvider 没有返回预期的数据:

import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { MockedProvider } from '@apollo/client/testing';
import { useDecider, GET_DECIDER } from './useDecider';

const getMock = (value = false, decider = '') => [
  {
    request: {
      query: GET_DECIDER,
      variables: {
        name: decider
      }
    },
    result: () => {
      console.log('APOLLO RESULT');

      return {
        data: {
          deciders: [
            {
              decision: value,
              name: decider,
              value: 10
            }
          ]
        }
      };
    }
  }
];

const FakeComponent = ({ decider }) => {
  const { enabled } = useDecider(decider);
  return <div>{enabled ? 'isEnabled' : 'isDisabled'}</div>;
};

const WrappedComponent = ({ decider, value }) => (
  <MockedProvider mocks={getMock(value, decider)} addTypename={false}>
    <FakeComponent decider={decider} />
  </MockedProvider>
);

describe('useDecider', () => {
  it('when decider returns true', () => {
    // should return true
    render(<WrappedComponent decider="fake_decider" value={true} />);
    screen.debug();
    const result = screen.getByText('isEnabled');
    expect(result).toBeInTheDocument();
  });
});

【问题讨论】:

  • 您能否提供有关MockedProvider 返回的内容的更多信息?或者也许是一个代码框?
  • MockedProvider 是从@apollo 导出的:import { MockedProvider } from '@apollo/client/testing'; 我正在尝试关注文档apollographql.com/docs/react/development-testing/testing
  • 我的意思是,MockedProvider 在您的测试中返回的数据是什么?你说数据不是预期的。
  • 没什么,data = undefined。我添加了console.log(loading, data) and loading = true`,但我从来没有看到它切换到false

标签: javascript reactjs apollo react-apollo apollo-client


【解决方案1】:

我简化了你的钩子实现并整理了一个working example

import { useQuery, gql } from "@apollo/client";

export const GET_DECIDER = gql`
  query GetDecider($name: [String]!) {
    deciders(names: $name) {
      decision
      name
      value
    }
  }
`;

export const useDecider = (name) => {
  const { data } = useQuery(GET_DECIDER, { variables: { name } });
  return { enabled: data?.deciders[0]?.decision || false };
};

请注意,在测试中,我还将您的 getBy 更新为 await findBy

describe("useDecider", () => {
  it("when decider returns true", async () => {
    // should return true
    render(<WrappedComponent decider="fake_decider" value={true} />);
    screen.debug();
    const result = await screen.findByText("isEnabled");
    expect(result).toBeInTheDocument();
  });
});

这是因为您需要等待 API 调用完成,然后数据才会出现在页面上,因此您不会期望数据在第一次呈现时就在那里。

【讨论】:

  • 尝试了您的实现,但测试失败
  • 你更新测试了吗?该代码正在我发布的链接上运行。
  • 如果您从测试中排除结果,那是不正确的。不知道为什么测试通过了。
  • 不确定你的意思。我记录了结果并得到了
    isEnabled
    。我错过了什么吗?您能否更新沙盒以显示什么不起作用?
  • 重启后它在代码沙箱中工作,但我将完全相同的测试和更新复制到 useDecider 到本地,但由于某种原因它失败了
【解决方案2】:

来自https://www.apollographql.com/docs/react/development-testing/testing/#testing-the-success-state

要测试您的组件在查询完成后是如何呈现的,您 可以在执行检查之前等待零毫秒超时。 这会将检查延迟到事件循环的下一个“滴答”,这 为 MockingProvider 提供了填充模拟结果的机会

在您的期望调用之前尝试添加

  await act(async () => {
    await new Promise((resolve) => setTimeout(resolve, 0));
  });

【讨论】:

    猜你喜欢
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 2021-10-14
    • 2016-07-12
    • 1970-01-01
    相关资源
    最近更新 更多