使用 testing-library 和 jest 测试 React 组件抛出的错误

Bha*_*hah 4 reactjs jestjs react-context react-testing-library

遵循这篇文中解释的 Kent C Dodds 的提供者模式,我有一个上下文提供者组件以及一个使用该上下文的钩子。

钩子防止在提供者之外使用它,

export function useUser() {
  const { user } = useContext(UserContext) || {};
  const { switchUser } = useContext(SwitchUserContext) || {};
  if (!user || !switchUser) {
    throw new Error('Cannot use `useUser` outside of `UserProvider`');
  }
  return { user, switchUser };
}
Run Code Online (Sandbox Code Playgroud)

为了测试场景,我创建了一个TestComponent并在其中使用了useUser钩子。

function TestComponent() {
  const { user, switchUser } = useUser();
  return (
    <>
      <p>User: {user.name}</p>
      <button onClick={switchUser}>Switch user</button>
    </>
  );
}
Run Code Online (Sandbox Code Playgroud)

我是这样测试的

  test('should throw error when not wrapped inside `UserProvider`', () => {
    const err = console.error;
    console.error = jest.fn();
    let actualErrorMsg;
    try {
      render(<TestComponent />);
    } catch(e) {
      actualErrorMsg = e.message;
    }
    const expectedErrorMsg = 'Cannot use `useUser` outside of `UserProvider`';
    expect(actualErrorMsg).toEqual(expectedErrorMsg);

    console.error = err;
  });
Run Code Online (Sandbox Code Playgroud)

我目前必须模拟console.error,然后在测试结束时将其设置为原始值。有用。但我想让它更具声明性和更简单。有没有好的模式来实现它?也许使用.toThrow() 的东西?

我有一个用于此的代码和,上面的代码可以在UserContext.js和 中找到UserContext.test.js

注意:测试可以在Tests标签下的代码和框本身中运行。

Phi*_*che 5

正如您已经提到的那样expect().toThrow():)

所以在你的情况下:

  test("should throw error when not wrapped inside `UserProvider`", () => {
    expect(() => render(<TestComponent />))
      .toThrow("Cannot use `useUser` outside of `UserProvider`");
  });
Run Code Online (Sandbox Code Playgroud)

关于console.error:目前设计上无法关闭默认错误日志。如果你想隐藏错误,你仍然需要模拟console.error.

当您模拟函数时,console.error您想在afterEach回调中恢复它们,以便在测试失败时也恢复它们。

  • 我能够通过像这样模拟来抑制 console.log 错误: `const consoleErrorFn = jest.spyOn(console, 'error').mockImplementation(() =&gt; jest.fn());` 不要忘记`jest.restoreMocks()` 如果你确实沿着这条路走下去。 (12认同)
  • 这似乎不起作用。我收到“错误:未捕获[错误:无法在“UserProvider”之外使用“useUser”]” (4认同)
  • 你是对的,测试确实通过了:)仍然记录了一个未被捕获的错误。放入 try catch 不起作用。有没有办法捕获测试中的错误? (2认同)
  • 它实际上是mockRestore:``consoleErrorFn.mockRestore()``` (2认同)