paint-brush
Java でのテスト: 主要な概念 [パート 1: 単体テスト]@gromspys
1,621 測定値
1,621 測定値

Java でのテスト: 主要な概念 [パート 1: 単体テスト]

Sergei Korneev10m2023/11/14
Read on Terminal Reader

長すぎる; 読むには

この記事では、簡単なコード例、パラメータ化、例外テスト、アノテーションなど、Java 単体テストの主要な概念について説明します。
featured image - Java でのテスト: 主要な概念 [パート 1: 単体テスト]
Sergei Korneev HackerNoon profile picture

単体テストは、コードの信頼性と正確性を保証するソフトウェア開発の基本的な実践です。この記事では、簡単なコード例、パラメータ化、例外テスト、 @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@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 の紹介

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プラグイン

コード カバレッジは、単体テストによって実行されるコード行、分岐、またはステートメントの割合を測定します。これは、テストされていないコードや追加のテストが必要な可能性のある領域を特定するのに役立ちます。


Maven は Java プロジェクト用の人気のあるビルド ツールであり、JaCoCo などのプラグインを使用してコード カバレッジ分析を Maven プロジェクトに統合できます。 JaCoCo をプロジェクトに追加する方法は次のとおりです。


  1. プロジェクトのpom.xmlファイルを開きます。
  2. JaCoCo Maven プラグイン構成を追加します。
 <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 では、統合テストのエキサイティングな世界に飛び込みますので、お楽しみに!