mcpField
S
spring-boot-test-patterns

spring-boot-test-patterns

github.com/giuseppe-trisciuoglioテスト・品質3654.3k 回インストール7 週間前に更新
リポジトリ

spring-boot-test-patterns について

JUnit 5、Mockito、Testcontainersを使うSpring Boot開発者向けのテストパターンガイドです。単体・スライス・統合テストを整理し、テスト範囲の選択とSpringコンテキストの負荷管理に役立ちます。

主な機能

  1. 01Mockitoによる単体テスト
  2. 02レイヤー別のSpringテストスライス
  3. 03MockMvcによるREST APIテスト
  4. 04Testcontainersのサービス接続
  5. 05依存関係とCI/CDのガイド

活用シーン

  1. 01サービスやリポジトリの分離テスト
  2. 02実データベースを使う統合テスト
  3. 03RESTコントローラーとAPIの検証
  4. 04自動テストパイプラインの構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill spring-boot-test-patterns

インストール後、Claude Code で/spring-boot-test-patternsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api-reference.md
best-practices.md
ci-cd-configuration.md
slice-testing.md
test-dependencies.md
testcontainers-setup.md
unit-testing.md
workflow-patterns.md

詳細

Spring Boot のテストパターン

概要

JUnit 5、Mockito、Testcontainers、およびパフォーマンスを最適化したスライステストパターンを使用して、Spring Boot アプリケーション向けの堅牢なテストスイートを作成するための包括的なガイダンスです。

使用する場面

  • モック化した依存関係を使用して、サービスやリポジトリのユニットテストを作成する場合
  • Testcontainers を使って実際のデータベースを用いた統合テストを実装する場合
  • @WebMvcTest または MockMvc を使って REST API をテストする場合
  • Spring Boot 3.5+ でコンテナー管理に @ServiceConnection を設定する場合

クイックリファレンス

テストの種類アノテーション目標時間用途
ユニットテスト@ExtendWith(MockitoExtension.class)< 50msSpring コンテキストを使わないビジネスロジック
リポジトリテスト@DataJpaTest< 100ms最小限のコンテキストでのデータベース操作
コントローラーテスト@WebMvcTest / @WebFluxTest< 100msREST API レイヤーのテスト
統合テスト@SpringBootTest< 500msコンテナーを使用した完全なアプリケーションコンテキスト
Testcontainers@ServiceConnection / @Testcontainersさまざま実際のデータベース/メッセージブローカーのコンテナー

主な概念

テストアーキテクチャの考え方
  1. ユニットテスト — Spring コンテキストを使わない、高速で分離されたテスト(< 50ms)
  2. スライステスト — 特定のレイヤーに限定した最小限の Spring コンテキスト(< 100ms)
  3. 統合テスト — 実際の依存関係を使用する完全な Spring コンテキスト(< 500ms)
主なアノテーション

Spring Boot テスト:

  • @SpringBootTest — 完全なアプリケーションコンテキスト(使用は最小限にしてください)
  • @DataJpaTest — JPA コンポーネントのみ(リポジトリ、エンティティ)
  • @WebMvcTest — MVC レイヤーのみ(コントローラー、@ControllerAdvice)
  • @WebFluxTest — WebFlux レイヤーのみ(リアクティブコントローラー)
  • @JsonTest — JSON シリアライズコンポーネントのみ

Testcontainers:

  • @ServiceConnection — Testcontainer を Spring Boot に接続します(3.5+)
  • @DynamicPropertySource — 実行時に動的プロパティを登録します
  • @Testcontainers — Testcontainers のライフサイクル管理を有効にします

手順

1. ユニットテストのパターン

モック化した依存関係を使ってビジネスロジックをテストします。

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    void shouldFindUserByIdWhenExists() {
        when(userRepository.findById(1L)).thenReturn(Optional.of(user));
        Optional<User> result = userService.findById(1L);
        assertThat(result).isPresent();
        verify(userRepository).findById(1L);
    }
}

高度なパターンについては、unit-testing.md を参照してください。

2. スライステストのパターン

特定のレイヤーに絞ったテストスライスを使用します。

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestContainerConfig
class UserRepositoryIntegrationTest {
    @Autowired
    private UserRepository userRepository;

    @Test
    void shouldSaveAndRetrieveUser() {
        User saved = userRepository.save(user);
        assertThat(userRepository.findByEmail("[email protected]")).isPresent();
    }
}

すべてのスライスパターンについては、slice-testing.md を参照してください。

3. REST API テストのパターン

MockMvc でコントローラーをテストします。

@WebMvcTest(UserController.class)
class UserControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    void shouldGetUserById() throws Exception {
        mockMvc.perform(get("/api/users/1"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.email").value("[email protected]"));
    }
}
4. @ServiceConnection を使った Testcontainers

Spring Boot 3.5+ でコンテナーを設定します。

@TestConfiguration
public class TestContainerConfig {
    @Bean
    @ServiceConnection
    public PostgreSQLContainer<?> postgresContainer() {
        return new PostgreSQLContainer<>("postgres:16-alpine");
    }
}

テストクラスに @Import(TestContainerConfig.class) を付けて適用します。 詳細な設定については、testcontainers-setup.md を参照してください。

5. 依存関係の追加

必要なテスト依存関係を含めます。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>1.19.0</version>
    <scope>test</scope>
</dependency>

依存関係の一覧については、test-dependencies.md を参照してください。

6. CI/CD の設定

自動テスト用に GitHub Actions を設定します。

name: Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      docker:
        image: docker:20-dind
    steps:
    - uses: actions/checkout@v4
    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        distribution: 'temurin'
    - name: Run tests
      run: ./mvnw test

CI/CD のパターン全体については、ci-cd-configuration.md を参照してください。

検証チェックポイント

テストを実装した後、以下を確認してください。

  • コンテナーの起動:docker ps(testcontainer イメージを確認します)
  • コンテキストの読み込み:「Started Application in X.XX seconds」が起動ログに出力されていることを確認します
  • テストの分離:テストを個別に実行し、相互に干渉しないことを確認します

例

@ServiceConnection を使った完全な統合テスト
@SpringBootTest
@Import(TestContainerConfig.class)
class OrderServiceIntegrationTest {

    @Autowired
    private OrderService orderService;

    @Autowired
    private UserRepository userRepository;

    @Test
    void shouldCreateOrderForExistingUser() {
        User user = userRepository.save(User.builder()
            .email("[email protected]")
            .build());

        Order order = orderService.createOrder(user.getId(), List.of(
            new OrderItem("SKU-001", 2)
        ));

        assertThat(order.getId()).isNotNull();
        assertThat(order.getStatus()).isEqualTo(OrderStatus.PENDING);
    }
}
実際のデータベースを使った @DataJpaTest
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestContainerConfig
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    void shouldFindByEmail() {
        userRepository.save(User.builder()
            .email("[email protected]")
            .build());
        assertThat(userRepository.findByEmail("[email protected]"))
            .isPresent();
    }
}

エンドツーエンドの例については、workflow-patterns.md を参照してください。

ベストプラクティス

  • 適切なテストの種類を使用する:リポジトリには@DataJpaTest、コントローラーには@WebMvcTest、完全な統合テストの場合にのみ@SpringBootTestを使用します
  • @ServiceConnectionを優先する:Spring Boot 3.5+では、コンテナー管理を簡潔にするため、@DynamicPropertySourceよりも@ServiceConnectionを優先します
  • テストの決定性を保つ:@BeforeEachですべてのテストデータを明示的に初期化します
  • レイヤーごとに整理する:コンテキストキャッシュを最大限に活用できるよう、テストをレイヤーごとにグループ化します
  • TestcontainersをJVMレベルで再利用する(withReuse(true) + TESTCONTAINERS_REUSE_ENABLE=true)
  • @DirtiesContextを避ける:コンテキストの再構築を強制するため、パフォーマンスが大幅に低下します
  • 外部サービスはモックし、必要な場合にのみ実際のデータベースを使用します
  • パフォーマンスの目標:ユニットテスト < 50ms、スライステスト < 100ms、統合テスト < 500ms

制約と警告

  • 絶対に必要な場合を除き、@DirtiesContextは使用しないでください(コンテキストの再構築を強制します)
  • 異なる設定の@MockBeanを混在させないでください(別々のコンテキストが作成されます)
  • TestcontainersにはDockerが必要です。CI/CDパイプラインでDockerがサポートされていることを確認してください
  • テストの実行順序に依存しないでください。各テストは独立している必要があります
  • @TestPropertySourceの使用には注意してください(別々のコンテキストが作成されます)
  • ユニットテストに@SpringBootTestを使用しないでください。代わりに通常のMockitoを使用してください
  • 異なる@MockBean設定によってコンテキストキャッシュが無効になる場合があります
  • テストでは変更可能な静的状態を避けてください(不安定なテストの原因になります)

参考資料

コメント