使用 jest 测试方法时声明 class 组件中没有更新

State no updating in class component when testing method with jest

我正在尝试在上下文提供程序中测试我的方法。我在要涵盖的方法中有一个分支,这就是我正在扼杀的。只有在特定条件发生时才进入特定分支:if (offset !== 0 && total !== 0 && offset >= total)

查看下面我的 Class 组件:

class JourneyProvider extends Component<
  {
    children: ReactNode;
  },
  JourneyContextData
> {
  constructor(props: { children: ReactNode }) {
    super(props);
    this.state = {
      ...defaultValues,
    };
  }

  getContextValue = (): JourneyContextData => {
    const { products, total, limit, offset, loading, disabled, setProducts } =
      this.state;
    return {
      products,
      total,
      limit,
      offset,
      loading,
      disabled,
      setProducts,
    };
  };

  setProducts = async (): Promise<void> => {
    const { limit, offset, total, products } = this.state;
    if (total === 0 || offset < total) {
      const gqlRequest = new GQLRequest(query);
      this.setLoading(true);
      try {
        await gqlRequest.post().then(({ products: { edges, totalCount } }) => {
          const newOffset = offset + limit;
          this.setState({
            products,
            total: totalCount,
            offset: newOffset,
          });
          this.setLoading(false);
          // Disable button if there are no more products
          if (offset !== 0 && total !== 0 && offset >= total) {
            // never gets in here when testing.
            this.setDisabled(true);
          }
        });
      } catch (e) {
        this.setLoading(false);
      }
    }
  };
}

这是我的测试:

  it("setProducts is successful and disable button", async () => {
    const wrapper = shallow(
      <JourneyProvider>
        <div>test</div>
      </JourneyProvider>
    ) as any;

    const result = {
      products: {
        edges: [
          {
            node: {
              id: "1",
              name: "test-name",
            },
          },
        ],
        totalCount: 1,
      },
    };

    mockedClient.post.mockResolvedValueOnce(result);

    jest
      .spyOn(ProductsQuery, "getProductsQuery")
      .mockResolvedValueOnce(new Query("test", true) as never);

    const setLoadingSpy = jest.spyOn(wrapper.instance(), "setLoading");
    const setDisabledSpy = jest.spyOn(wrapper.instance(), "setDisabled");

    wrapper.state().limit = result.products.totalCount;
    console.log(wrapper.state().offset); //this returns 0
    await wrapper.instance().setProducts();
    console.log(wrapper.state().offset); //this returns 0
    expect(setLoadingSpy).toHaveBeenCalledWith(true); // this passes

    expect(setLoadingSpy).toHaveBeenCalledWith(false); // this passes

    expect(setDisabledSpy).toHaveBeenCalledWith(true); // this fails
  });

您应该更改进行比较的代码中的逻辑,因为您使用的是陈旧状态,请记住,调用 setState 不会立即更改状态。将您设置的新值与状态而不是旧状态值进行比较

          if (newOffset !== 0 && totalCount !== 0 && newOffset >= totalCount) {

或者将该代码放入 setState 回调中以保证您使用更新的值

...
          const newOffset = offset + limit;
          this.setState({
            products,
            total: totalCount,
            offset: newOffset,
          }, () => {
            this.setLoading(false);
            if (offset !== 0 && total !== 0 && offset >= total) {
              this.setDisabled(true);
            }
          });
...