为什么异步测试中的“ then”部分会开玩笑地失败?

时间:2020-05-02 15:51:06

标签: reactjs redux jestjs enzyme aws-amplify

组件:

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()setError块返回catch,这是为什么呢?它应该从setList块返回then。我究竟做错了什么? response变量返回mockList很好。

修改 它返回的错误是API not configured,我正在使用aws放大。

1 个答案:

答案 0 :(得分:1)

fetchList在安装组件时被调用,模拟的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())...