単体テストは、コードの信頼性と正確性を保証するソフトウェア開発の基本的な実践です。この記事では、簡単なコード例、パラメータ化、例外テスト、 @Before
、 @BeforeEach
、 @After
、 @AfterEach
などのアノテーション、モックとスタブの使用など、Java 単体テストの主要な概念について説明します。 。
また、モック用の人気のある Mockito ライブラリを紹介し、Maven プラグインを使用してコード カバレッジを測定するためのガイダンスも提供します。
単体テストは、個々のコンポーネントまたはコード単位を分離してテストし、その正しさを検証する実践です。主な目標は、開発プロセスの早い段階でバグを検出して修正し、コードの各ユニットが期待どおりに動作することを保証することです。
まずは、例で使用できる簡単な計算機クラスを作成しましょう。 Calculator
クラスには、基本的な算術演算が含まれています。
public class Calculator { public int add(int a, int b) { return a + b; } public int subtract(int a, int b) { return a - b; } public int multiply(int a, int b) { return a * b; } public int divide(int a, int b) { return a / b; } }
Calculator
クラスの単体テストを作成するには、Java の一般的なテスト フレームワークである JUnit フレームワークを使用できます。 add
メソッドの簡単な単体テストを作成してみましょう。
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class CalculatorTest { @Test public void testAdd() { Calculator calculator = new Calculator(); int result = calculator.add(2, 3); assertEquals(5, result); } }
このテストでは、必要な JUnit クラスをインポートし、テスト メソッドに@Test
のアノテーションを付けます。次に、 Calculator
クラスのインスタンスを作成し、 add
メソッドの結果が期待値 (5) と等しいことをアサートします。
パラメーター化されたテストを使用すると、複数の入力データ セットを使用して同じテスト ロジックを実行できます。これは、さまざまな入力値を使用してメソッドをテストする場合に便利です。 JUnit でこれを行うには、 @ParameterizedTest
アノテーションを使用し、入力値と期待される結果をパラメーターとして指定します。以下に例を示します。
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import static org.junit.jupiter.api.Assertions.assertEquals; public class CalculatorTest { @ParameterizedTest @CsvSource({"2, 3, 5", "4, 7, 11", "0, 0, 0"}) public void testAdd(int a, int b, int expected) { Calculator calculator = new Calculator(); int result = calculator.add(a, b); assertEquals(expected, result); } }
この例では、 @ParameterizedTest
アノテーションを使用して、入力値と期待される結果の複数のセットを CSV 形式で提供できます。テスト メソッドは組み合わせごとに実行され、 add
メソッドの正確性が保証されます。
コードでエラーが適切に処理されることを確認するには、例外をテストすることが重要です。例外ケースをテストするには、JUnit が提供するassertThrows
メソッドとともに@Test
アノテーションを使用できます。
以下に例を示します。
javaCopy codeimport org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertThrows; public class CalculatorTest { @Test public void testDivideByZero() { Calculator calculator = new Calculator(); assertThrows(ArithmeticException.class, () -> calculator.divide(5, 0)); } }
このテストでは、 Calculator
クラスで数値をゼロで除算するとArithmeticException
がスローされることを検証します。
@Before
、 @BeforeEach
、 @After
、 @AfterEach
などのアノテーションは、テスト環境のセットアップと破棄に使用されます。これらのアノテーションは、一般的なテストの初期化タスクとクリーンアップ タスクの管理に役立ちます。
@Before
と@After
それぞれ、テスト クラス内のすべてのテスト メソッドの前と後に 1 回実行されます。@BeforeEach
と@AfterEach
、各テスト メソッドの前後に実行されます。
以下に例を示します。
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class CalculatorTest { private Calculator calculator; @BeforeEach public void setUp() { calculator = new Calculator(); } @AfterEach public void tearDown() { calculator = null; } @Test public void testAdd() { int result = calculator.add(2, 3); assertEquals(5, result); } @Test public void testSubtract() { int result = calculator.subtract(5, 3); assertEquals(2, result); } }
この例では、 setUp
メソッドに@BeforeEach
の注釈が付けられ、各テストの前にCalculator
オブジェクトを初期化します。 @AfterEach
の注釈が付けられたtearDown
メソッドは、各テストの後にリソースをクリーンアップします。
モックとスタブは、テスト対象のコードをデータベースや Web サービスなどの外部依存関係から分離する場合の単体テストに不可欠です。これらの依存関係の動作をシミュレートできます。
Calculator
クラスを拡張して外部依存関係を含むメソッドを含めてから、その依存関係をシミュレートするスタブを作成しましょう。
public class Calculator { private ExternalService externalService; public Calculator(ExternalService externalService) { this.externalService = externalService; } public int performComplexCalculation(int a, int b) { int result = externalService.multiply(a, b); return result + externalService.getConstant(); } }
この更新されたCalculator
クラスでは、 performComplexCalculation
乗算と定数値の取得をExternalService
に依存します。
実際のExternalService
に依存せずにCalculator
クラスをテストするスタブを作成する方法を次に示します。
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.*; public class CalculatorTest { @Test public void testPerformComplexCalculation() { // Create a stub for ExternalService ExternalService externalServiceStub = new ExternalService() { @Override public int multiply(int a, int b) { return a * b; } @Override public int getConstant() { return 5; // Stubbed constant value } }; // Create the Calculator with the stubbed ExternalService Calculator calculator = new Calculator(externalServiceStub); // Test the performComplexCalculation method int result = calculator.performComplexCalculation(2, 3); assertEquals(11, result); // 2*3 + 5 (constant) = 11 } }
このテストでは、必要なメソッドをオーバーライドする匿名クラスを作成することにより、テスト メソッド内でExternalService
がスタブ化されます。このようにして、 Calculator
テスト メソッドは、 ExternalService
の実際の実装に依存せずに実行されます。
スタブは、外部システムまたは依存関係の動作をシミュレートして、クラスまたはメソッドの特定の機能を分離してテストするのに役立ちます。これにより、実際の外部サービスを必要とせずに、スタブの動作を制御し、テスト対象のユニットに集中することができます。
Mockito は、モック オブジェクトを作成および管理するための人気のある Java ライブラリです。外部の支払いゲートウェイと対話するPaymentService
クラスがあるとします。 Mockito を使用して、支払いゲートウェイのモックを作成できます。
import org.junit.jupiter.api.Test; import static org.mockito.Mockito.*; public class PaymentServiceTest { @Test public void testProcessPayment() { PaymentGateway paymentGateway = mock(PaymentGateway.class); PaymentService paymentService = new PaymentService(paymentGateway); when(paymentGateway.charge(100.0)).thenReturn(true); boolean result = paymentService.processPayment(100.0); assertTrue(result); verify(paymentGateway, times(1)).charge(100.0); } }
この例では、モックPaymentGateway
を作成し、 when
メソッドを使用してその動作を定義します。次に、 PaymentService
クラスのprocessPayment
メソッドを呼び出し、予期されたパラメーターを使用してcharge
メソッドが呼び出されたことを確認します。
コード カバレッジは、単体テストによって実行されるコード行、分岐、またはステートメントの割合を測定します。これは、テストされていないコードや追加のテストが必要な可能性のある領域を特定するのに役立ちます。
Maven は Java プロジェクト用の人気のあるビルド ツールであり、JaCoCo などのプラグインを使用してコード カバレッジ分析を Maven プロジェクトに統合できます。 JaCoCo をプロジェクトに追加する方法は次のとおりです。
pom.xml
ファイルを開きます。 <build> <plugins> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.7</version> <executions> <execution> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
次のコマンドを使用して Maven ビルドを実行します。
mvn clean verify
ビルドを実行すると、 target/site/jacoco/index.html
ファイルにコード カバレッジ レポートが表示されます。このレポートは、単体テストによるコードのカバレッジに関する詳細情報を提供します。
Java 単体テストは、コードの信頼性と正確性を確保するために不可欠な実践です。 JUnit や Mockito などのツールを使用すると、コンポーネントの効果的な単体テストやモックを作成できます。
コード カバレッジ分析を Maven および JaCoCo と統合することで、テストがコードベースの重要な部分を確実にカバーできるようになります。単体テストを定期的にテストして保守することは、高品質で堅牢な Java アプリケーションを作成するのに役立ちます。
このシリーズの次のパートでは、システム全体が正しく機能することを確認するために、さまざまなコンポーネントとサービス間の相互作用をテストするソフトウェア テストの重要な側面である統合テストについて説明します。
パート 2 では、統合テストのエキサイティングな世界に飛び込みますので、お楽しみに!