使用 try/catch 测试 useEffect 钩子

Dar*_*ala 8 reactjs jestjs enzyme react-hooks

我需要测试catch获取数据请求何时被拒绝,但我不明白为什么错误没有被捕获,并且出现此错误:

UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)

我有这样的情况:

export const Container = ({fetchFirstAsset, fetchSecondAsset}) => {
  const [status, setStatus] = useState(null);

  async function fetchAssets() {
    setStatus(IN_PROGRESS);

    try {
      await fetchFirstAsset();
      await fetchSecondAsset()

      setStatus(SUCCESS);
    } catch {
      setStatus(FAILURE);
    }
  }

  useEffect(() => {
    fetchAssets();
  }, []);

  ....
};
Run Code Online (Sandbox Code Playgroud)

我这样测试:

import {mount} from 'enzyme';
import {act} from 'react-dom/test-utils';

const fetchFirstAsset = jest.fn();
const fetchSecondAsset = jest.fn();

it('should render without errors', async () => {
  fetchFirstAsset.mockReturnValueOnce(Promise.resolve());
  fetchSecondAsset.mockReturnValueOnce(Promise.reject());
  let component;

  await act(async () => {
    component = mount(
      <Container
        fetchFirstAsset={fetchFirstAsset}
        fetchSecondAsset={fetchSecondAsset}
      />
    );
  });

  expect(fetchSomething).toHaveBeenCalled();
});
Run Code Online (Sandbox Code Playgroud)

如果我在fetchSomething解决问题时测试Promise.resolve()一切正常并且测试通过,但是当我尝试Promise.reject()测试时catch案例时,则不会捕获此错误并且我有unhandled promise rejection

(如果您想知道为什么代码看起来像这样:在应用程序的其他地方,我使用 redux 处理状态更改,因此 catch 的测试很容易,但在一个地方,我需要为组件获取 3 个不同的资产,我决定处理状态的变化,useState因为从 redux 中提取 3 个不同的状态并将其组合起来会很丑陋。useState我认为 with 更干净)

预先感谢您的帮助!:)

小智 5

这是一个很好的方法,您需要在其中声明函数useEffect()并实现try/catch其中的块,而在函数外部您只需调用它

(另外,不要忘记清理你的useEffect()

useEffect(() => {
  const fetchAssets = async () => {
    setStatus(IN_PROGRESS);

    try {
      await fetchFirstAsset();
      await fetchSecondAsset()

      setStatus(SUCCESS);
    } catch {
      setStatus(FAILURE);
    }
  }

  fetchAssets();
}, [])
Run Code Online (Sandbox Code Playgroud)


Red*_*ron 0

你需要像这样编写你的 catch 块:

catch (e) {
     // can do something with e in here
      setStatus(FAILURE);
    }
Run Code Online (Sandbox Code Playgroud)