Состояние отсутствие обновления в компоненте класса при тестировании метода с помощью jest

#reactjs #jestjs #state #enzyme

Вопрос:

Я пытаюсь протестировать свой метод в поставщике контекста. У меня есть одна ветвь в методе, которую нужно охватить, и это то, чем я задыхаюсь. Конкретная ветвь вводится только при выполнении определенного условия: if (offset !== 0 amp;amp; total !== 0 amp;amp; offset >= total)

Смотрите мой компонент класса ниже:

 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 amp;amp; total !== 0 amp;amp; 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
  });
 

Комментарии:

1. Попробуйте обернуть все методы, которые обновляют состояния реакции, действием(() => {})>

Ответ №1:

Вам следует изменить логику в коде, в котором вы проводите сравнение, потому что вы используете устаревшее состояние, имейте в виду, что вызов setState не изменяет состояние немедленно. Сравните новые значения, которые вы установили для состояния, вместо старых значений состояния

           if (newOffset !== 0 amp;amp; totalCount !== 0 amp;amp; newOffset >= totalCount) {

 

или поместите этот код в обратный вызов setState, чтобы гарантировать, что вы используете обновленные значения

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