【问题标题】:React Hook test with useState for internal state使用 useState 对内部状态进行 React Hook 测试
【发布时间】:2020-08-03 18:15:59
【问题描述】:

我一直在研究大量资源以使用带有 React Hook 的 useState 来测试内部状态,但仍然找不到满意的答案,一些测试用例正在从 mountshallow 获取预期值,这将显示在 UI 端而不是从组件的内部状态(useState)显示,如果组件没有在 UI 端暴露状态值怎么办,例如:

const TestComponent = () => {
  const [count, setCount] = React.useState(0);

  return (
    <span>
      <button id="count-up" type="button" onClick={() => setCount(count + 1)}>Count Up</button>
    </span>
  );
}

如何编写测试用例进行测试

1) 当组件挂载时,我的内部状态count会被初始化为0?

2) 当组件在按钮count-up 上模拟onClick 事件时,应该调用我的setCount 并且我的内部状态count 应该变为1?

【问题讨论】:

  • 如果你将钩子移到一个单独的文件中会更容易,然后我们可以单独测试钩子本身(例如使用像github.com/testing-library/react-hooks-testing-library这样的库)。如果要测试绑定到组件的钩子,测试IMO的最佳方法是模拟点击并直接检查结果。
  • @JeeMok,嗨,你有我可以参考的例子吗?我不确定应该将哪个部分移到单独的文件中,因为您可以看到我的组件已经很小了...
  • @JeeMok useState 钩子是 React 的一部分,它已经在一个单独的文件中。

标签: reactjs jestjs react-hooks enzyme


【解决方案1】:

你可以在 React 上使用jest.spyOn 来查看组件是否调用了setState 钩子,一个简单的测试示例:

import React from "react";
import App from "./app";
import Enzyme, { shallow } from "enzyme";
import Adapter from "enzyme-adapter-react-16";

Enzyme.configure({ adapter: new Adapter() });

describe("App", () => {
  it("should call setState with initial values on component mount", () => {
    const mockSetState = jest.spyOn(React, "useState");

    shallow(<App />);

    expect(mockSetState).toHaveBeenCalledTimes(1);
    expect(mockSetState).toHaveBeenCalledWith(5);
  });
});

您也可以将useState 移动到单独的文件中,并将其用作自定义挂钩(可能是不必要的层,由您决定)

// useCounter.js
import { useState, useCallback } from "react";

const useCounter = initialValue => {
  const [count, setValue] = useState(initialValue);
  const setCount = useCallback(x => setValue(x), []);
  return { count, setCount };
};

export default useCounter;
// usage: app.js
function App() {
  const { count, setCount } = useCounter(5);
  return (
    <div className="App">
      <h1>Testing React Hooks</h1>
      <p>{count}</p>
      <button onClick={() => setCount(count - 1)}>-</button>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  );
}

然后您可以对“自定义”挂钩进行测试:

import { renderHook, act } from "@testing-library/react-hooks";
import useCounter from "./useCounter";

test("should increment counter", () => {
  const { result } = renderHook(() => useCounter(0));

  act(() => {
    result.current.setCount(1);
  });

  expect(result.current.count).toEqual(1);
});

代码沙盒上的工作示例

【讨论】:

  • 感谢您的详细教程!这可能是一个单独的问题。第一种方式,当我使用shallow(&lt;App /&gt;)查看快照时,总是显示null,而我的expect(mockSetState).toHaveBeenCalledTimes(1)失败并收到0,请问您对此类问题有经验或知识吗?
  • Enzyme 可能不是测试快照的最佳工具,shallowmount 对于检查道具和触发事件和生命周期很有用。要测试快照,也许您想尝试react-test-renderer 库?这里有一个简单的解释来了解 Enzyme 方法和区别以及何时使用:gist.github.com/fokusferit/e4558d384e4e9cab95d04e5f35d4f913
猜你喜欢
  • 1970-01-01
  • 2021-11-13
  • 2020-07-21
  • 2021-01-24
  • 2021-06-03
  • 1970-01-01
  • 2021-09-22
  • 2020-09-22
  • 1970-01-01
相关资源
最近更新 更多