使用 useState 进行内部状态的 React Hook 测试

Kev*_*ing 3 reactjs jestjs enzyme react-hooks

我一直在研究大量资源,通过使用 useState 和 React Hook 来测试内部状态,但仍然找不到满意的答案,一些测试用例正在获取预期值或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>
  );
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能写一个测试用例来测试

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

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

Jee*_*Mok 6

您可以jest.spyOn在 React 上使用来查看组件是否调用了钩子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);
  });
});
Run Code Online (Sandbox Code Playgroud)

您还可以将其移至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;
Run Code Online (Sandbox Code Playgroud)
// 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>
  );
}
Run Code Online (Sandbox Code Playgroud)

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

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);
});
Run Code Online (Sandbox Code Playgroud)

代码沙盒上的工作示例

编辑测试 React Hooks