Reactアプリケーションの品質を向上させるには、ユニットテストが重要です。この章では、Reactでのユニットテストの基本、React Testing LibraryとTypeScriptの活用法、型を活用したテストの設計について解説します。
Reactでのユニットテスト
ユニットテストは、個々のコンポーネントや関数が期待通りに動作することを確認するためのテストです。Reactでは、主に以下のツールが使用されます:
- Jest: JavaScript向けのテストフレームワーク。
- React Testing Library (RTL): ユーザー視点でコンポーネントをテストするためのライブラリ。
基本的なユニットテストの例
以下は、Reactコンポーネントをテストする基本的な例です。
コンポーネント
tsx
const Button = ({ label }: { label: string }) => {
return <button>{label}</button>;
};
export default Button;
テストコード
tsx
import { render, screen } from '@testing-library/react';
import Button from './Button';
test('renders button with label', () => {
render(<Button label="Click me" />);
const buttonElement = screen.getByText(/click me/i);
expect(buttonElement).toBeInTheDocument();
});
解説
render
: コンポーネントを仮想DOMにレンダリング。screen.getByText
: レンダリングされたDOMから要素を取得。expect(...).toBeInTheDocument
: 要素が存在することを確認。
React Testing LibraryとTypeScriptの活用
React Testing Library (RTL)は、ユーザーインターフェースを操作するようなテストを書くためのライブラリです。TypeScriptと組み合わせることで、型安全なテストを書くことができます。
型付きのPropsテスト
コンポーネント
tsx
interface InputProps {
value: string;
onChange: (value: string) => void;
}
const Input = ({ value, onChange }: InputProps) => {
return (
<input
type="text"
value={value}
onChange={(e) => onChange(e.target.value)}
/>
);
};
export default Input;
テストコード
tsx
import { render, screen, fireEvent } from '@testing-library/react';
import Input from './Input';
test('calls onChange with the correct value', () => {
const handleChange = jest.fn();
render(<Input value="" onChange={handleChange} />);
const inputElement = screen.getByRole('textbox');
fireEvent.change(inputElement, { target: { value: 'hello' } });
expect(handleChange).toHaveBeenCalledWith('hello');
});
解説
fireEvent.change
: 入力イベントをシミュレート。jest.fn
: モック関数を作成し、呼び出し状況を検証可能。
テストで型を活用する方法
型を使用することで、テストの設計や実行時に発生しうるエラーを防ぐことができます。
型でPropsの正確性を保証
型を活用することで、間違ったPropsの使用をテストで検知できます。
tsx
interface ButtonProps {
label: string;
disabled?: boolean;
}
const Button = ({ label, disabled = false }: ButtonProps) => {
return <button disabled={disabled}>{label}</button>;
};
export default Button;
テストコード
tsx
import { render, screen } from '@testing-library/react';
import Button from './Button';
test('renders disabled button when disabled is true', () => {
render(<Button label="Submit" disabled={true} />);
const buttonElement = screen.getByText(/submit/i);
expect(buttonElement).toBeDisabled();
});
型安全なモックAPI
モックAPIを利用する際にも型を活用することで、レスポンスの整合性を保つことができます。
tsx
interface User {
id: number;
name: string;
}
const mockFetchUser = jest.fn<Promise<User>, []>(() => {
return Promise.resolve({ id: 1, name: 'John Doe' });
});
test('fetches user successfully', async () => {
const user = await mockFetchUser();
expect(user.name).toBe('John Doe');
});
ReactとTypeScriptを組み合わせたユニットテストでは、型を活用することでテストの安全性と保守性が向上します。React Testing Libraryと組み合わせることで、ユーザー視点のテストを効率的に記述でき、アプリケーションの品質を高めることが可能です。