JotaiJotai

상태
React를 위한 기본적이고 유연한 상태 관리

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 + 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 예제

물론, 여러분도 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')
})