网站搜索

reactjs - 我需要渲染一个自定义 Hook,并在有人尝试在没有提供者的情况下使用该 Hook 时测试错误信息


使用 React、Jest 和 React 测试库

我的自定义钩子

import { useContext } from "react";

import { SelectThemeContext } from "../contexts/SelectThemeContext/SelectThemeContextProvider";

import { isEmpty } from "../utils/functions/isEmpty";

const useSelectThemeContext = () => {
  const context = useContext(SelectThemeContext);

  if (isEmpty(context)) {
    throw Error(
      "You have to use useSelectThemeContext inside <SelectThemeContextProvider />",
    );
  }

  const { theme, toggleTheme } = context;
  return { theme, toggleTheme };
};

export default useSelectThemeContext;

我的测试

it("[ACAMP-03] - should return error message when trying to use custom hook without provider", async () => {
    let message: string;
    try {
      await renderHook(() => useSelectThemeContext());
      message = "";
    } catch (e: any) {
      message = e.message;
    }

    expect(message).toEqual(
      "You have to use useSelectThemeContext inside <SelectThemeContextProvider />",
    );
  });

我可以接收到消息,但控制台也显示错误。

在 VirtualConsole。(node_modules/jsdom/lib/jsdom/virtual-console.js:29:45) 在 reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:70:28)
在 innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:341:9) 在 invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
在 HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9) 在 HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17) 在 HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)

console.error
  The above error occurred in the <TestComponent> component:
  
      at TestComponent (C:\Users\rafael.almeida\Documents\Projects\Estudo\acamp\base-reactv18-eslint-prettier-config\node_modules\@testing-library\react\dist\pure.js:281:5)
  
  Consider adding an error boundary to your tree to customize error handling behavior.
  Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.

  at logCapturedError (node_modules/react-dom/cjs/react-dom.development.js:18687:23)
  at update.callback (node_modules/react-dom/cjs/react-dom.development.js:18720:5)
  at callCallback (node_modules/react-dom/cjs/react-dom.development.js:13923:12)
  at commitUpdateQueue (node_modules/react-dom/cjs/react-dom.development.js:13944:9)
  at commitLayoutEffectOnFiber (node_modules/react-dom/cjs/react-dom.development.js:23391:13)
  at commitLayoutMountEffects_complete (node_modules/react-dom/cjs/react-dom.development.js:24688:9)  
  at commitLayoutEffects_begin (node_modules/react-dom/cjs/react-dom.development.js:24674:7)
  at commitLayoutEffects (node_modules/react-dom/cjs/react-dom.development.js:24612:3)

运行测试 CodeSandBox 测试 CodeSandBox

答案#1

你可以/应该使用 @testing-library/react-hooks。它提供了一个不同的 renderHook 方法,可以接受一个 wrapper 参数,并且可以返回错误。

你的测试看起来将会像这样。我认为它不一定非要是异步的。如果你的具体需求需要一个异步函数,那么请参考 jest 文档。我记得这跟我原本对异步测试的预期有点不同。

import { renderHook } from "@testing-library/react-hooks";

it("[ACAMP-03] - should return error message when trying to use custom hook without provider", () => {
    const { result } = renderHook(() => useSelectedThemeContext());

    expect(result.error?.message).toEqual(
      "You have to use useSelectThemeContext inside <SelectThemeContextProvider />",
    );
  });

如果你想测试与提供商的功能,你可以这样做。

it("does what the hook is supposed to do", () => {
    const wrapper = ({ children }) => (
        <SelectedThemeContextProvider>
            {children}
        </SelectedThemeContextProvider>
    );

    const { result } = renderHook(() => useSelectedThemeContext(), {wrapper});

    expect(result.error).toBeUndefined();

    // using color as an example
    expect(result.color).toEqual("#ffffff");
})

答案#2

我正在使用一种方法专门抑制 console.error 以进行测试,如果算法有设计成不需要使用这个的方法,请...

const spyConsole = jest
  .spyOn(console, "error")
  .mockImplementation(() => {});