【问题标题】:How to mock fetch function inside useEffect?如何在 useEffect 中模拟 fetch 函数?
【发布时间】:2023-03-23 18:20:01
【问题描述】:

这就是我在useEffect 钩子中的函数的外观:

useEffect(() => {
    const getImages = async () => {
      try {
        setIsLoading(true);
        const response = await fetch(GET_RECENT_IMAGES_API_URL(pageNumber));

        if (!response.ok) {
          throw new Error("Network response was not ok");
        }

        const imageData = await response.json();

        setIsLoading(false);

        const appImaegDataArray: CoreImageData[] = imageData.photos.photo.map(
          (image: ResponseImageData) => {
            const { id, server, secret, title, ownername } = image;

            const coreImageDataObj: CoreImageData = {
              id,
              server,
              secret,
              title,
              ownername,
              isFavorite: checkIfFavorited(id),
            };

            return coreImageDataObj;
          }
        );
        setAllImages((prevAllImagesState) => {
          const newestImagesArray = [
            ...prevAllImagesState,
            ...appImaegDataArray,
          ];
          return getUniqueImagesArray(newestImagesArray);
        });

        setHasMore(imageData.photos.pages > pageNumber);
      } catch (error) {
        console.error(error);
        setIsLoading(false);
      }
    };
    getImages();
    // eslint-disable-next-line
  }, [pageNumber]);

这是我模拟请求的方法:

global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () =>
      Promise.resolve({
        photos: {
          pages: 10,
          photo: [
            {
              id: "51159068217",
              owner: "50123236@N03",
              secret: "dda285148c",
              server: "65535",
              farm: 66,
              title: "Blythe a Day May 5–Magical",
              ispublic: 1,
              isfriend: 0,
              isfamily: 0,
            },
          ],
        },
      }),
  })
) as jest.Mock;

describe("<ImageList />", () => {
  it("loads all images on mount", async () => {
    render(<ImageList isViewFavoriteImages={false} />);
    await waitFor(() =>
      expect(screen.getByText("Blythe a Day May 5–Magical")).toBeInTheDocument()
    );
  });
});

但是,执行此操作时,我收到错误并且测试失败。这是失败测试的输出:

修复测试的最佳方法是什么?

【问题讨论】:

    标签: reactjs jestjs react-testing-library


    【解决方案1】:
    global.fetch = jest.fn(() => ({
      json: ...,
      ok: true,
      status: 200,
    })
    

    虽然我会建议not to mock fetch。而是将其提取到服务方法并模拟它..?

    // my-service.js
    
    export const fetchFoo = () => {
      return fetch(...)
    }
    
    // my-test.spec.js
    
    jest.mock('./my-service', () => jest.fn(() => Promise.resolve('some-value'));
    

    【讨论】:

    • 感谢您的回答。但是,您能否更详细地解释我应该如何重构这些功能?我在问,因为我不知道如何处理 setLoadingsetHasMore,因为它们直接取决于 getImages 函数内部发生的事情。
    • getImages 可以按原样进行测试,无需重构(尽管您可以通过将一些逻辑提取到方法中以使其更具可读性来稍微清理一下)原始测试是失败是因为 fetch 没有被正确模拟,如果你将逻辑移动到服务并模拟该服务,它应该可以工作
    猜你喜欢
    • 2021-11-26
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    相关资源
    最近更新 更多