테스트 — Jest와 React Native Testing Library
테스트 코드는 리팩토링의 안전망이며, 면접에서 "테스트를 작성해본 경험"은 큰 가산점입니다.
설치
npm install -D jest @testing-library/react-native @testing-library/jest-native
컴포넌트 테스트
// components/Counter.tsx
function Counter() {
const [count, setCount] = useState(0);
return (
<View>
<Text testID="count-text">{count}</Text>
<Pressable testID="increment-btn" onPress={() => setCount((c) => c + 1)}>
<Text>+1</Text>
</Pressable>
</View>
);
}
// __tests__/Counter.test.tsx
import { render, fireEvent, screen } from '@testing-library/react-native';
import Counter from '../components/Counter';
describe('Counter', () => {
it('초기값이 0이다', () => {
render(<Counter />);
expect(screen.getByTestId('count-text')).toHaveTextContent('0');
});
it('버튼을 누르면 카운트가 증가한다', () => {
render(<Counter />);
fireEvent.press(screen.getByTestId('increment-btn'));
expect(screen.getByTestId('count-text')).toHaveTextContent('1');
});
});
비동기 테스트
import { render, waitFor, screen } from '@testing-library/react-native';
// API를 호출하는 컴포넌트 테스트
jest.mock('../api/userApi', () => ({
getUsers: jest.fn(() => Promise.resolve([
{ id: '1', name: '홍길동' },
{ id: '2', name: '김철수' },
])),
}));
it('사용자 목록을 로드하여 표시한다', async () => {
render(<UserList />);
// 로딩 상태 확인
expect(screen.getByTestId('loading')).toBeTruthy();
// 데이터 로드 완료 대기
await waitFor(() => {
expect(screen.getByText('홍길동')).toBeTruthy();
expect(screen.getByText('김철수')).toBeTruthy();
});
});
커스텀 Hook 테스트
import { renderHook, act } from '@testing-library/react-native';
function useCounter(initial = 0) {
const [count, setCount] = useState(initial);
const increment = () => setCount((c) => c + 1);
const reset = () => setCount(initial);
return { count, increment, reset };
}
describe('useCounter', () => {
it('초기값으로 시작한다', () => {
const { result } = renderHook(() => useCounter(5));
expect(result.current.count).toBe(5);
});
it('increment 호출 시 카운트가 증가한다', () => {
const { result } = renderHook(() => useCounter());
act(() => result.current.increment());
expect(result.current.count).toBe(1);
});
});
네비게이션 테스트
import { NavigationContainer } from '@react-navigation/native';
import { render, fireEvent, screen } from '@testing-library/react-native';
// 네비게이션 래퍼
function renderWithNavigation(component: React.ReactElement) {
return render(
<NavigationContainer>{component}</NavigationContainer>
);
}
it('상세 화면으로 이동한다', () => {
renderWithNavigation(<AppNavigator />);
fireEvent.press(screen.getByText('상세 보기'));
expect(screen.getByText('상세 화면')).toBeTruthy();
});
정리
testID를 사용하면 구현과 분리된 안정적인 테스트를 작성할 수 있습니다- ** 비동기 테스트 **는
waitFor를 사용하여 상태 변화를 기다립니다 - 네이티브 모듈은
jest.mock()으로 모킹합니다 - 테스트는 ** 사용자 행동 기준 **으로 작성하세요 — 내부 구현이 아닌 결과를 검증합니다
- 커스텀 Hook은
renderHook으로 독립적으로 테스트할 수 있습니다
댓글 로딩 중...