Testing
Testing Library의 가이드 원칙을 그대로 따릅니다:
- "테스트가 소프트웨어가 사용되는 방식과 비슷할수록, 더 많은 신뢰를 얻을 수 있다."
여러분이 작성하는 테스트가 사용자가 아톰과 컴포넌트와 상호작용하는 방식과 비슷하도록 권장합니다. 따라서 Jotai를 구현 세부사항으로 취급하세요.
React Testing Library를 사용한 예제입니다:
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 } from '@testing-library/react'import userEvent from '@testing-library/user-event'import { Counter } from './Counter'test('should increment counter', () => {// 준비render(<Counter />)const counter = screen.getByText('0')const incrementButton = screen.getByText('one up')// 실행await userEvent.click(incrementButton)// 검증expect(counter.textContent).toEqual('1')})
주입된 값
테스트를 시작하기 전에 아톰에 임의의 값을 주입하고 싶을 수 있습니다. 예를 들어, 카운터가 100을 넘지 않도록 제한하고 싶을 수 있습니다. 이제 카운터가 100에 도달한 후 더 이상 증가하지 않는지 테스트하는 방법을 살펴보겠습니다. 이를 위해 Provider를 사용하고, 아톰을 채울 수 있도록 내보내면 됩니다.
import React from 'react'import { render, screen } from '@testing-library/react'import userEvent from '@testing-library/user-event'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')await userEvent.click(incrementButton)expect(counter.textContent).toEqual('100')})
커스텀 훅
복잡한 아톰이 있는 경우, 독립적으로 테스트하고 싶을 때가 있습니다.
이때 React Hooks Testing Library를 사용할 수 있습니다. 아래 예제를 참고하세요.
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 예제
물론, 여러분도 Provider
를 사용하거나 사용하지 않고 동일한 방식으로 React-Native 컴포넌트를 테스트할 수 있습니다.
import React from 'react'import { render, fireEvent } from '@testing-library/react-native'import { Counter } from './counter'test('카운터가 증가해야 함', () => {// 준비const { getByText } = render(<Counter />)const counter = getByText('0')const incrementButton = getByText('one up')// 실행fireEvent.press(incrementButton)// 검증expect(counter.props.children.toString()).toEqual('1')})