ZOZO開発組織の2021年の振り返りと現状 - Qiita
株式会社ZOZO 技術本部 本部長の @sonots です。この記事は ZOZOのAdvent Calendar 2021のカレンダー 1の最終回(25日目)です。 ...
https://qiita.com/sonots/items/629b8d5785c04ae9c953
こんにちは、マイグレーションチームの寺嶋です。
本記事では、ZOZOTOWNのマイクロサービスにおけるデータベースを参照したユニットテストの改善で得られた知見や工夫について紹介します。
ZOZOTOWNでは、数年前からリプレイスプロジェクトが実施されており、いくつものマイクロサービスが誕生しました。初期にJavaで作られたマイクロサービスのユニットテストが開発環境のデータベースを参照しており、テストで利用しているデータが更新・削除されてしまうとテストに失敗してしまうことが度々起きていました。また、接続しているデータベースがオンプレのSQL Serverを利用しており、CI上でユニットテストを実施できない状況でした。
そのため対象のユニットテストは次の問題を抱えていました。
このようなことから外部環境に依存しないユニットテストへ変更する必要がありました。
対象サービスの技術スタック
今回改善するマイクロサービスの技術スタックは次の通りです。
ZOZOTOWNリプレイスプロジェクトでは全社技術スタックを統一しています。詳しくは下記の記事をご覧ください。
解決方法として次の方法を検討しました。
H2データベースはJVM上にて動作するデータベースでインストールを必要としません。JDBCのURLに ;MODE=MySQL といったオプションをつけることでH2データベースの挙動をMySQL、PostgreSQLなど切り替えることができます。もちろんSQL Serverモードもあり、 ;MODE=MSSQLServer を指定すればSQL Server風の挙動を再現させることが可能になります。ただ、H2のドキュメントを確認していると、 ヒント句は破棄される という説明があり、SQLチューニングでヒント句を使用しているサービスなので、採用は見送ることになりました。
ということで、DockerコンテナでSQL Serverを起動させてテストする方法となり、見つけたのが Testcontainers でした。
TestcontainersはJUnitのテストをサポートするJavaライブラリです。一般的なデータベースやSelenuim、Dockerコンテナで実行できるものを軽量で使い捨て可能なインスタンスとして提供してくれます。Testcontainersを利用すると次の種類のテストが簡単に行えます。
MySQL、PostgreSQL、Oracle Databaseなどのコンテナ化されたインスタンスを使用して、データアクセスレイヤーにコードの変更なくテストを実行できます。Dockerコンテナを利用するので複雑なセットアップも必要ありません。
データベース、メッセージキュー、Webサーバなどの依存関係を使用してアプリケーションのテストを実行できます。
自動化されたUIテストを実施するためにSelenuimと互換性のあるコンテナを使用し、ブラウザの状態やバージョンを気にすることなくテストを実施できます。また、失敗したテストのみ動画を録画するなども行ってくれます。
今回は データアクセスレイヤーテスト を活用して、実データベースを参照しているテストを改善します。
Testcontainersの依存関係をpom.xmlに追記していきます。今回はSQL Serverコンテナをユニットテスト時に起動しますのでorg.testcontainers.mssqlserverを追加しています。MySQLやPostgreSQL、Oracle Databaseを利用する場合は対象データベースのdependencyがありますので、環境に応じて指定してください。
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.16.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mssqlserver</artifactId>
<version>1.16.3</version>
<scope>test</scope>
</dependency>
MSSQLServerContainerクラスがSQL Serverコンテナを管理するクラスとなっており、これを継承し新たにMyMSSQLContainerクラスを作っていきます。
続きはこちら