为什么 'then' 部分在异步测试中开玩笑地失败了?

Why does the 'then' part in async test fail in jest?

分量:

export const fetchList = () => {
  return API.get(AMPLIFY_ENPOINTS.default, API_URLS.list, { response: true });
}

const List: React.FC = () => {
  const dispatch = useDispatch();
  const setError = useError();

  useEffect(() => {
    fetchList()
      .then((response) => {
        if (response && response.data?.length) {
          dispatch(setList(response.data));
        }
      })
      .catch((error) => {
        setError(error);
      });
  }, [])
}

测试:

it('should fetch list', async () => {
  const wrapper = mount(
    <Provider store={store}>
      <List />
    </Provider>
  );
  API.get = jest.fn().mockImplementation(() => Promise.resolve({ data: mockList }));
  const response = await fetchList();
  console.log(store.getActions(), response); // HERE IS THE ISSUE
});

所以 store.getActions() returns setError 来自 catch 块,这是为什么呢?它应该 return setList 来自 then 块。我究竟做错了什么? response变量returns mockList就好了。

编辑 returns 的错误是 API not configured,我正在使用 aws amplify。

fetchList 在组件挂载时调用,mocked API.get 不影响第一次调用,第二次调用不做任何事情。通过为它们分配间谍来模拟方法是一种不好的做法,因为它们在测试后无法恢复。

fetchList 的问题在于它不能被侦测或模拟,因为它在定义的同一个模块中使用。它在 useEffect 中创建的承诺无法链接,需要刷新承诺以避免竞争条件。

可以是:

  let flushPromises = () => new Promise(resolve => setImmediate(resolve));

  jest.spyOn(API, 'get').mockResolvedValue({ data: mockList });

  const wrapper = mount(
    <Provider store={store}>
      <List />
    </Provider>
  );

  await flushPromises();

  expect(store.getActions())...