JotaiJotai

状態
Primitive and flexible state management for React

测试

我们呼应 测试库的指导原则

  • “你的测试越像你的软件的使用方式,他们就越能给你信心。”

我们鼓励您编写测试,就像用户会与您的原子和组件交互一样, 因此将 Jotai 视为实现细节。

下面是一个使用 React 测试库 的示例:

Counter.tsx:

import { atom, useAtom } from "jotai";
const countAtom = atom(0);
export function Counter() {
const [count, setCount] = useAtom(countAtom);
return (
<h1>
<p>{count}</p>
<button onClick={() => setCount((c) => c + 1)}>one up</button>
</h1>
);
}

Counter.test.ts:

import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import { Counter } from "./Counter";
test("should increment counter", () => {
// Arrange
render(<Counter />);
const counter = screen.getByText("0");
const incrementButton = screen.getByText("one up");
// Act
fireEvent.click(incrementButton);
// Assert
expect(counter.textContent).toEqual("1");
});

注入值

在开始某些测试之前,您可能希望向您的原子注入任意值。 也许计数器应该限制在 100。我们来看看如何测试它达到 100 后不增加。 为此,只需使用 Provider,然后导出要填充的原子。

import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import { countAtom, Counter } from "./Counter";
import { Provider } from "jotai";
const CounterProvider = () => {
return (
<Provider initialValues={[[countAtom, 100]]}>
<Counter />
</Provider>
);
};
test("should not increment on max (100)", () => {
render(<CounterProvider />);
const counter = screen.getByText("100");
const incrementButton = screen.getByText("one up");
fireEvent.click(incrementButton);
expect(counter.textContent).toEqual("100");
});

自定义 Hook

如果你有复杂的原子,有时你想单独测试它们。

为此,您可以使用 React Hooks 测试库。 下面是一个例子:

countAtom.ts:

import { useAtom } from "jotai";
import { atomWithReducer } from "jotai/utils";
const reducer = (state: number, action?: "INCREASE" | "DECREASE") => {
switch (action) {
case "INCREASE":
return state + 1;
case "DECREASE":
return state - 1;
case undefined:
return state;
}
};
export const countAtom = atomWithReducer(0, reducer);

countAtom.test.ts:

import { renderHook, act } from "@testing-library/react-hooks";
import { useAtom } from "jotai";
import { countAtom } from "./countAtom";
test("should increment counter", () => {
const { result } = renderHook(() => useAtom(countAtom));
act(() => {
result.current[1]("INCREASE");
});
expect(result.current[0]).toBe(1);
});

使用 React-Native 的示例

当然,你也可以用同样的方式测试 React-Native 组件,有或没有 Provider

import React from "react";
import { render, fireEvent } from "@testing-library/react-native";
import { Counter } from "./counter";
test("should increment counter", () => {
// Arrange
const { getByText } = render(<Counter />);
const counter = getByText("0");
const incrementButton = getByText("one up");
// Act
fireEvent.press(incrementButton);
// Assert
expect(counter.props.children.toString()).toEqual("1");
});