我需要渲染自定义挂钩并测试错误消息时,当有人尝试使用挂钩的情况下,没有提供商

发布于 2025-02-11 09:24:00 字数 2906 浏览 1 评论 0原文

使用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/living/helpers/runtime-script-errors.js:70:28)
在innininvokeeventlisteners(node_modules/jsdom/lib/jsdom/living/living/eventtarget-impl.js:341:9) 在IndokeEventListeners(node_modules/jsdom/lib/jsdom/living/events/eventtarget-impl.js:274:3)
在htmlunknownelementimpl._dispatch上 在htmlunknownelementimpl.dispatchevent(node_modules/jsdom/lib/jsdom/living/events/eventtarget-impl.js:94:17) 在htmlunknownelement.dispatchevent(node_modules/jsdom/lib/jsdom/living/living/endenated/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)

Using React, Jest and react testing library

My custom hook

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;

My test

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 />",
    );
  });

I can get the message but I also get an error in the console.

at VirtualConsole. (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:70:28)
at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:341:9)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
at 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)

Run test CodeSandBox
Test CodeSandBox

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

空心↖ 2025-02-18 09:24:00

您可以/应该使用@testing-library/reaction/react-hooks 。它提供了一种不同的renderhook方法,可以接受包装器参数,并且可以返回错误。

然后,您的测试看起来像这样。我不认为它一定是异步。如果您的特定要求需要异步函数,请参考 jest docs 。我记得这与我对测试异步的期望有所不同。

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");
})

You can/should use @testing-library/react-hooks. It provides a different renderHook method that can accept a wrapper parameter, and can return errors.

Your test would then look something like this. I don't believe it has to be async. If your specific requirements require an async function, then refer to the jest docs. I remember this was a bit different than what I expected for testing async.

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 />",
    );
  });

If you want to test the functionality with the provider you can do something like this.

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");
})
☆獨立☆ 2025-02-18 09:24:00

我正在使用一种抑制控制台的方法。专门用于测试,如果该算法是为不需要使用此算法的方法而设计的,请...

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

i'm using a means to suppress the console.error specifically for testing, if the algorithm is designed for a way to not need to use this please...

const spyConsole = jest
  .spyOn(console, "error")
  .mockImplementation(() => {});
§对你不离不弃 2025-02-18 09:24:00

我能够通过嘲笑 usecontext 返回来测试和涵盖错误处理线。

import React from 'react';
import { renderHook } from '@testing-library/react';

import { useSelectThemeContext} from '../your-path';

describe('useSelectThemeContext', () => {
  it("[ACAMP-03] - should return error message when trying to use custom hook without provider", () => {
    jest.spyOn(React, 'useContext').mockImplementation(() => null)
    try {
      renderHook(useSelectThemeContext);
    }
    catch (error) {
      expect(error).toEqual(new Error("You have to use useSelectThemeContext inside <SelectThemeContextProvider />"))
    }
  });
})

I was able to test and cover the error handling line by mocking the useContext return.

import React from 'react';
import { renderHook } from '@testing-library/react';

import { useSelectThemeContext} from '../your-path';

describe('useSelectThemeContext', () => {
  it("[ACAMP-03] - should return error message when trying to use custom hook without provider", () => {
    jest.spyOn(React, 'useContext').mockImplementation(() => null)
    try {
      renderHook(useSelectThemeContext);
    }
    catch (error) {
      expect(error).toEqual(new Error("You have to use useSelectThemeContext inside <SelectThemeContextProvider />"))
    }
  });
})
打小就很酷 2025-02-18 09:24:00

来自 应从@testing-library/react导入React 18 -library/react-hooks 。还有另一个由于他们需要在同意构建此功能之前就需要有记录的API,因此停滞不前。因此,现在我正在做的是要捕获错误而不是控制台。

it('should error with message', () => {
  const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
  try {
    renderHook(() => failingHook());
  } catch (error) {
    expect((error as Error).message).toEqual('Expected error');
  }
  spy.mockRestore();
});

From this issue that renderHook for React 18 should be imported from @testing-library/react which does not expose the result.error property like the one exported from @testing-library/react-hooks. And there is another issue that seems to be stalled since they are requiring a documented API before agreeing to build this functionality back in. So for now here is what I'm doing in order to catch the error and not console.error the expected error:

it('should error with message', () => {
  const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
  try {
    renderHook(() => failingHook());
  } catch (error) {
    expect((error as Error).message).toEqual('Expected error');
  }
  spy.mockRestore();
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文