コンテンツに移動
アプリケーション開発

Spring Boot アプリケーションの一貫した開発とテスト

2023年9月20日
Google Cloud Japan Team

※この投稿は米国時間 2023 年 9 月 8 日に、Google Cloud blog に投稿されたものの抄訳です。

アプリケーションをローカルで設定し、インメモリ データベースでテストを行い、環境と SQL 言語の間の不一致を取捨選択するために、数多くの作業を手動で実施する必要はもうありません。また、分散システムによくあるネットワーク障害をテストできない、という状況にも対応できます。

Google Cloud の Twelve-Factor App を構築するデベロッパーは、GCP の本番環境で実行する場合と同じコンテナ化されたアプリケーションの依存関係によって一貫した開発、デバッグ、テストをローカルで行う方法、つまり Twelve-Factor App の 10 番目の要素、開発環境から本番環境までの環境パリティを追求しています。

Google の Java 用 Cloud クライアント ライブラリと Spring Cloud GCP を使用することで、本番環境に対応したクラウド ネイティブな Spring Boot アプリケーションの移行または新規のビルドを簡単に行えます。デベロッパーは短時間でアプリケーションをスピンアップし、ビジネス ロジックの作成に注力できます。

このブログ投稿では、Google Cloud の開発環境から本番環境までの環境パリティを実現するという目標に従って、ローカルで一貫した開発、デバッグ、テストを行い、Google Cloud の Spring Boot Java アプリケーションの開発エクスペリエンスを大幅に改善(そして高速化)する方法に焦点を当てます。

Google Cloud のエミュレータ、Testcontainers、Spring Boot が問題を解決

Testcontainers は、データベース、メッセージ ブローカー、ウェブブラウザ、その他のカスタム Docker コンテナの使い捨てかつ軽量のインスタンスを提供するオープンソースのフレームワークです。これにより、モックの作成や複雑な環境構成が不要になります。Testcontainers を使用すると、テストの依存関係をコードとして定義してからテストを実行するだけでコンテナが作成されます。このコンテナは、テストのライフサイクルの最後に削除されます。

Google の Cloud SDK には、Google Cloud Platform によって提供されるプロダクトやサービスとやり取りするためのライブラリとツールが用意されています。Testcontainers のモジュールは、さまざまな依存関係から成る構成済みのコンテナ化された実装であり、これによってテストの記述が非常に簡単になります。

現時点で、Testcontainers の Google Cloud モジュールは、Bigtable、Datastore、Firestore、Spanner、Pub/Sub の GCP エミュレータを Java およびその他の言語でサポートしています。

Spring Boot 3.1 に Testcontainers のサポートが追加され、すべてのアプリケーションの依存関係(データベース、メッセージング システム、キャッシュ メカニズム、依存サービス)を、ローカルでアプリケーションを実行またはテストするときに自動的に開始するよう構成できるようになりました。

Testcontainers で Spring Boot アプリケーションをテストする方法について詳しくは、こちらのスタートガイドをご覧ください。

開発タスク

詳細な説明に進む前に、通常デベロッパーが担当するタスクの一部について再確認しましょう。

  • 各機能、つまりクラスやメソッドなどの単体テストを作成する

  • (ドメイン)サービス インテグレーション テストを作成し、依存アプリケーションまたはクラウド サービスとのインテグレーションを含む、ドメイン運用とビジネスルールをテストする

  • アプリケーション テストを作成し、アプリケーションとそのウェブ コントローラの機能テストを実施する

  • ネットワーク障害テストを作成し、ソースコードが該当する障害を処理するかどうかを評価する(カオス エンジニアリングのベスト プラクティスの一環)

  • アプリの依存関係によるローカル開発

ブログのソースコード

このブログ投稿では一連の Spring Boot サンプルアプリを利用し、Cloud Firestore およびオープンソースの Postgres(Cloud SQL 向け)の Testcontainers の使用を主体としたテストを作成します。

Git リポジトリのクローンを作成し、Audit(Firestore)サービスと Quotes(Postgres)サービスで、それぞれのコンセプトに基づく実際の作業を体験しましょう。以降のサンプルでは Firestore を使用します。

テスト構成

まず、テストの依存関係として spring-boot-testcontainers を Maven の pom.xml に追加します。
読み込んでいます...

次に、200 を超える Google Java ライブラリすべてとの互換性を実現するために、Google クライアント ライブラリの部品表(BOM)を追加します。

読み込んでいます...

最後に、各アプリケーション依存サービスに依存関係を追加します。

読み込んでいます...

Testcontainers で Firestore のエミュレータのテストを行うには、@Container を構成し、その動的なプロパティをテストクラスに指定します。

例: Firestore サービスのテスト [テスト]

読み込んでいます...

Spring Boot 3.1 には Service Connections というコンセプトが導入されています。これは、対応するコンテナに対して必要な Spring Boot プロパティを自動的に構成するというものです。

Postgres の構成をまとめると次のようになります。

読み込んでいます...

(ドメイン)サービス / インテグレーション テストの作成

コンテナ化された Firestore のエミュレータでサービスをテストすることで、Cloud Firestore でコードをスムーズに実行できるという確信を得られます: [テスト]

読み込んでいます...

アプリケーション テストの作成

アプリケーション テストを作成すると、本番のクラウド環境で実行されている状態のアプリをテストできます。

たとえば、サービスがサーバーレスの環境で実行されており、イベント ドリブン アーキテクチャのコンポーネントだとします。CloudEvents はイベントデータを一般的な形で記述するための仕様であり、Firestore を対象とした Testcontainers を利用すると同時に、ウェブ コントローラで CloudEvents を使用して HTTP 呼び出しをテストできます: [テスト]

読み込んでいます...

ネットワーク障害テストの作成

分散ソフトウェアにおいて、クラウドで実行されるサービス間のネットワーク障害状況は、サービス提供に直接影響するため、大きなリスクとなります。クラウド環境でサービスを実行する前に、こうしたランダムな障害に対するサービス クライアント コードの復元性をコードベースでテストするとよいでしょう。障害が発生すると、アプリケーションが予期しない応答をしたり、圧力を受けて停止したりすることがあります。

このテストは、カオス エンジニアリングのベスト プラクティスの一環です。

ネットワーク障害状況をシミュレートするために、Shopify の Toxiproxy コンテナをテストコードとコンテナの間、またはコンテナとコンテナの間に配置します。[テスト]

読み込んでいます...

レイテンシによるタイムアウト、再試行、切断されたネットワーク接続をシミュレートできるようになりました。

たとえば、次のようにタイムアウトをシミュレートしてテストを行うことができます。

読み込んでいます...

アプリケーションの依存関係によるローカル開発

Spring Boot 3.1 以降では、通常の開発期間中も Testcontainers を使用して各依存サービスでアプリケーションのローカル実行およびデバッグを行えるようになりました。

余計な作業は必要ありません。/src/test/java のテスト クラスパスで TestAuditApplication クラスと TestcontainersConfig クラスを構成してアプリを起動するだけです。

アプリは、.with(TestcontainersConfig) を使用してアプリケーション ランチャーにアタッチされた TestcontainersConfig クラスで起動します。

読み込んでいます...

TestAuditApplication を IDE から、またはシンプルに次のコマンドを使用して実行できます。

読み込んでいます...

まとめ

Google Cloud のエミュレータ、Testcontainers、Spring Boot 3.1 を利用することで、Google Cloud アプリケーションの開発エクスペリエンスを大幅に改善(そして高速化)できます。Google Cloud の本番環境で実行する場合と同じコンテナ化されたアプリケーションの依存関係によって、つまり開発環境から本番環境までの環境パリティを維持することで、ローカルで一貫した開発、デバッグ、テストを行うことができます。

Google Cloud のエミュレータと Testcontainers を使用した Spring Boot アプリケーション開発の実務作業について詳しくは、こちらのコードベースをご覧ください。

ご質問やフィードバックがある場合は、Twitter で @ddobrin までお気軽にご連絡ください。

- エンタープライズ アプリ モダナイゼーション担当アーキテクト Dan Dobrin

投稿先