测试
我们回应了测试库的指导原则:
- "你的测试越像你的软件被使用的方式,它们就能给你更多的信心。"
我们鼓励你像用户会与你的原子和组件交互那样编写测试,因此将Jotai视为一个实现细节。
这里有一个使用React测试库的例子:
Counter.tsx
:
import { atom, useAtom } from 'jotai'export 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', () => {// Arrangerender(<Counter />)const counter = screen.getByText('0')const incrementButton = screen.getByText('one up')// ActfireEvent.click(incrementButton)// Assertexpect(counter.textContent).toEqual('1')})
注入值
你可能想在开始一些测试之前向你的原子注入任意值。也许计数器应该限制到100。让我们看看如何测试它在达到100后不会增加。为了做到这一点,只需使用一个Provider,并导出你的原子以便填充。
import React from 'react'import { render, screen, fireEvent } from '@testing-library/react'import { useHydrateAtoms } from 'jotai/utils'import { countAtom, Counter } from './Counter'import { Provider } from 'jotai'const HydrateAtoms = ({ initialValues, children }) => {useHydrateAtoms(initialValues)return children}const TestProvider = ({ initialValues, children }) => (<Provider><HydrateAtoms initialValues={initialValues}>{children}</HydrateAtoms></Provider>)const CounterProvider = () => {return (<TestProvider initialValues={[[countAtom, 100]]}><Counter /></TestProvider>)}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')})
自定义钩子
如果你有复杂的原子,有时你可能想要单独测试它们。
为此,你可以使用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 + 1case 'DECREASE':return state - 1case 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', () => {// 安排const { getByText } = render(<Counter />)const counter = getByText('0')const incrementButton = getByText('one up')// 执行fireEvent.press(incrementButton)// 断言expect(counter.props.children.toString()).toEqual('1')})