单元在几分钟内测试您的React钩子
#javascript #react #测试

单元测试是软件开发的基本实践,对于任何软件工程师来说尤为重要。
它涉及孤立地测试代码的单个单元或组件以确保它们按预期工作。
在React的背景下,这些单元通常是指应用程序代码库的各个功能,组件或小部分。

单位测试有两个重大收益

  1. 生活文档:单位测试是您代码库的生活文档的一种形式。单位测试不仅依靠评论或外部文档,而是提供了有关代码应如何行为的具体示例。只要您与代码一起维护测试,本文档将保持最新状态,在挂钩的情况下,这些测试用例将探索实现挂钩的不同方面。

  2. 预防回归:单位测试是未来变化的安全网。当您修改或扩展代码时,运行单元测试可以帮助您确保现有功能保持完整。如果您的任何更改都打破了预期的行为,测试将捕获它,从而使您可以在问题到生产之前解决问题。

执行

我们现在将创建一个具有历史功能的计数器钩。

在您的React应用程序中安装以下软件包

npm i use-state-with-history 

如果您不使用Create-React-app,则需要安装@testing-library/react

现在我们创建钩子

// src/use-counter.tsx

export function useCounterWithHistory(initialValue: number) {
  const [count, setCount, { backward, forward, go, history }] = useStateWithHistory<number>(initialValue);

  return [count, setCount, { backward, forward, go, history }];
}

我们现在喜欢测试案例:

// src/test/use-counter.test.tsx

import React from "react";
import { renderHook, screen } from "@testing-library/react";
import { useStateWithHistory } from "../use-counter";
import { act } from "react-dom/test-utils";

describe("Counter", () => {
  test("mounts a count of 0", async () => {
    const promise = Promise.resolve();
    const { result } = renderHook(() => useStateWithHistory<number>(0));
    expect(result.current[0]).toBe(0);
    await act(() => promise);
  });

  test("mounts a count of 0 and increments by one", async () => {
    const promise = Promise.resolve();
    const { result } = renderHook(() => useStateWithHistory<number>(0));
    act(() => result.current[1](result.current[0] + 1));
    expect(result.current[0]).toBe(1);
    await act(() => promise);
  });

  test("increments by one two times start with zero", async () => {
    const promise = Promise.resolve();
    const { result } = renderHook(() => useStateWithHistory<number>(0));
    act(() => {
      result.current[1](result.current[0] + 1);
    });

    act(() => {
      result.current[1](result.current[0] + 1);
    });
    expect(result.current[0]).toBe(2);
    await act(() => promise);
  });

  test("increments by one two times start with zero then goes back by 1 step", async () => {
    const promise = Promise.resolve();
    const { result } = renderHook(() => useStateWithHistory<number>(0));
    act(() => {
      result.current[1](result.current[0] + 1);
    });
    act(() => {
      result.current[1](result.current[0] + 1);
    });

    act(() => {
      result.current[2].backward();
    });
    expect(result.current[0]).toBe(1);
    await act(() => promise);
  });

  test("increments by one two times start with zero then goes back by 2 steps and one forward", async () => {
    const promise = Promise.resolve();
    const { result } = renderHook(() => useStateWithHistory<number>(0));
    act(() => {
      result.current[1](result.current[0] + 1);
    });
    act(() => {
      result.current[1](result.current[0] + 1);
    });

    act(() => {
      result.current[2].backward();
    });

    act(() => {
      result.current[2].backward();
    });

    act(() => {
      result.current[2].forward();
    });
    expect(result.current[0]).toBe(1);
    await act(() => promise);
  });

  test("increments by one two times start with zero then goes back by 2 steps and one forward then goes to 0", async () => {
    const promise = Promise.resolve();
    const { result } = renderHook(() => useStateWithHistory<number>(0));
    act(() => {
      result.current[1](result.current[0] + 1);
    });
    act(() => {
      result.current[1](result.current[0] + 1);
    });

    act(() => {
      result.current[2].backward();
    });

    act(() => {
      result.current[2].backward();
    });

    act(() => {
      result.current[2].forward();
    });
    act(() => {
      result.current[2].go(0);
    });
    expect(result.current[0]).toBe(0);
    await act(() => promise);
  });
});

您可以看到,我们有很多测试用例,我们想测试挂钩的所有可能用例,这可以确保我们保留了单位案例的living documentation目标。

还可以通过覆盖效果的情况进行任何更改,都可以确保它不会破坏现有的钩子案例。

注意:在嵌入事件的情况下,您需要将它们包装在act中。

result对象是一个react ref,因此进行act会突变钩的内部状态。

最后,您可以使用react-scripts

运行测试用例

如果您使用混音,下一个或任何自定义模板,则可以安装它,但是如果使用Create-Rexct-App,它已经安装了,如果您有自己的自定义测试设置,则可以跳过此部分

npx react-scripts test