【问题标题】:Testing Mocked Fetch Api in Jest returns undefined在 Jest 中测试 Mocked Fetch Api 返回 undefined
【发布时间】:2021-08-31 17:45:58
【问题描述】:

我在 React/TS 中有一个通用的 FetchService,如下所示:

/* Generic Fetch Service */


const FetchService = {
  call: async (url:string) => {
    try {
      return await fetch(url)
        .then((res) => res.json())
        .then((data) => { data.response});
    } catch (e) {
      throw Error(e);
    }
   }
}

export default FetchService

还有一个这样写的测试:

import FetchService from "../../services/Fetch.service";


it("should call Fetch Service", async () => {
  const val = { json: async () => [{ data: { response: "aaa" } }] };

  window.fetch = jest.fn().mockImplementationOnce((url) => {
    if (url === "localhost") {
         return Promise.resolve(val);
    }
  });

  const data = await FetchService.call("localhost");
  expect(data).toBe(undefined);
});

它确实成功覆盖了 success ,但它返回“未定义”,而不是我在测试响应时模拟的数据。如果我将 console.log 放入我的服务中,在 data.response 中,它将记录来自测试的“aaa”。

我做错了什么?

我已经在 StackOverflow 中尝试了所有答案,以及一些教程,但没有任何效果。

使用 Jest Docs 也没有多大帮助。

谁能帮帮我?

谢谢。

编辑:

感谢这里的两个答案解决了

/* Generic Fetch Service */

const FetchService = {
  call: async (url: string) => {
    try {
      const response = await fetch(url);
      const data = await response.json();

      console.log(data.response, "data111");
      return data.response;
    } catch (err) {
      throw err;
    }
  },
};
export default FetchService;

在测试中:

const val = {
 json: async () => {
   return { response: "aaa" };
 },
};

it("should call Fetch Service", async () => {
 window.fetch = jest.fn().mockImplementationOnce((url) => {
   if (url === "localhost") {
     return val;
   }
 });

 const data = await FetchService.call("localhost");

 expect(data).toBe("aaa");
});

【问题讨论】:

  • 它是否调用return Promise.resolve(val)?例如,如果您在同一 if 语句中将 console.log('resolving', val) 放在其上方?
  • @A_A 它记录:resolving { json: [AsyncFunction: json] }

标签: reactjs typescript unit-testing jestjs


【解决方案1】:

您在模拟中返回 [{ data: { response: "aaa" } }],然后在 FetchService 中获得 [{ data: { response: "aaa" } }].response(未定义)。

根据您的需要,您可以修改 FetchService 中的预期数据,或在您的模拟中提供不同的示例数据:

const FetchService = {
  call: (url:string) => {
    return fetch(url)
      .then((res) => res.json())
      .then((obj) => { obj[0].data.response});
  }
}

【讨论】:

  • 将 val const 更改为 thisconst val = { json: async () => 'aaa' }; 然后删除最后一个,工作。
【解决方案2】:

您尝试在不兼容的 Promise 链接时使用“异步”。你有两种方法可以解决这个问题。

// with async await
const FetchService = {
    call: async (url:string) => {
      try {
        const response = await fetch(url);
        const data = await response.json();
        return data.response;

      } catch (err) {
        throw err;
      }
     }
  }

//without async await (Promise chaining method)
const FetchService = {
  call: (url:string) => {
    
    return fetch(url)
      .then((res) => res.json())
      .then((data) => data.response)
      .catch(err => {
        throw err
      })
  }
}
  
  export default FetchService

【讨论】:

  • 很好,但我认为问题出在测试中,因为它仍然记录undefined
  • 将 val const 更改为此:const val = { json: async () => 'aaa' }; 然后最后删除,工作。
  • Async/Await 和 .then(...) 是兼容的。这是多余的,我总是会选择其中一个而不是两者,但它不应该破坏任何东西
猜你喜欢
  • 2019-08-04
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 2021-07-02
  • 2020-09-09
  • 2020-03-16
  • 2022-01-23
  • 2020-12-29
相关资源
最近更新 更多