Spring BootにおけるJUnit 5とMockitoを活用した単体テストの実装ガイド

単体テストの効率的な作成

Java開発において、IntelliJ IDEAなどのIDEを使用している場合、Command + Shift + T(Windows/LinuxではCtrl + Shift + T)のショートカットを利用することで、対象クラスに対応するテストクラスを素早く生成できます。

MockMvcを利用したコントローラーのテスト

Spring BootのMVCレイヤーをテストする場合、MockMvcを使用してHTTPリクエストをシミュレートするのが一般的です。以下に、リクエストヘッダーやJSONペイロードを含むテストの構成例を示します。

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import java.nio.charset.StandardCharsets;

@SpringBootTest
class ApiControllerTest {

    @Autowired
    private WebApplicationContext webContext;

    private MockMvc mockMvc;

    @BeforeEach
    void setup() {
        // MockMvcの初期化
        mockMvc = MockMvcBuilders.webAppContextSetup(webContext).build();
    }

    @Test
    void verifyGetEndpoint() throws Exception {
        MvcResult result = mockMvc.perform(
                MockMvcRequestBuilders.get("/api/v1/status")
                        .header("X-Custom-Header", "TestValue")
                        .contentType(MediaType.APPLICATION_JSON)
        )
        .andExpect(MockMvcResultMatchers.status().isOk())
        .andReturn();

        String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
        System.out.println("Response: " + responseBody);
    }
}

Mockitoによる依存コンポーネントのモック化

サービス層の依存関係を切り離してテストする場合、Mockitoを使用します。Spring Boot環境では、@MockBeanを使用することで、Springコンテキスト内のBeanをモックに差し替えることが可能です。

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

@SpringBootTest
public class OrderServiceTest {

    @MockBean
    private PaymentGateway paymentGateway;

    @Autowired
    private OrderService orderService;

    @Test
    public void processOrderTest() {
        // モックの振る舞いを定義
        Mockito.when(paymentGateway.authorize(Mockito.anyDouble()))
               .thenReturn("AUTH_SUCCESS");

        String status = orderService.completeOrder(1001L);
        assert "COMPLETED".equals(status);
    }
}

Mavenを利用している場合、以下の依存関係をpom.xmlに追加してテスト環境を構築します。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

JUnit 5の主要なアノテーション

JUnit 5(Jupiter)では、テストのライフサイクルを管理するために以下のアノテーションが用意されています。

  • @Test: メソッドをテストケースとして定義します。
  • @BeforeEach / @AfterEach: 各テストメソッドの実行前後に処理を行います。
  • @BeforeAll / @AfterAll: 全テストメソッドの実行前後に一度だけ処理を行います(staticメソッドである必要があります)。
  • @DisplayName: テスト結果に表示されるカスタム名を指定します。
  • @Disabled: テストの実行をスキップします。
  • @Timeout: 実行時間が指定を超えた場合に失敗させます。

アサーション(検証)メソッド

テスト結果が期待通りであるかを確認するために、多様なアサーションメソッドが提供されています。

メソッド 説明
assertEquals 期待値と実際の値が等しいか検証
assertNotSame オブジェクトの参照先が異なるか検証
assertTrue / assertFalse 条件が真または偽であるか検証
assertNotNull オブジェクトがnullでないか検証
assertThrows 特定の例外が発生するか検証
assertTimeout 指定時間内に処理が終了するか検証

高度なテスト手法

入れ子(Nested)テスト

@Nestedアノテーションを使用すると、関連するテストをグループ化して階層構造にでき、可読性が向上します。

import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

class ShoppingCartTest {

    @Nested
    class WhenEmpty {
        @Test
        void totalItemCountShouldBeZero() {
            // 検証ロジック
        }
    }

    @Nested
    class WhenItemsAdded {
        @Test
        void totalItemCountShouldIncrease() {
            // 検証ロジック
        }
    }
}

パラメータ化テスト

同じテストロジックを異なる入力値で繰り返し実行したい場合、@ParameterizedTestを利用します。

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertNotNull;

class ValidationTest {

    @ParameterizedTest
    @ValueSource(strings = {"Alice", "Bob", "Charlie"})
    void testWithNameInputs(String name) {
        assertNotNull(name);
        System.out.println("Checking: " + name);
    }
}

タグ: Spring Boot JUnit 5 Mockito Java mockmvc

8月15日 02:40 投稿