[WIP] kotlin> 単体テスト時にdockerイメージを使う > gradle-docker-compose-plugin


単体テスト時にdockerイメージを起動できる、GraldeのPluginである`gradle-docker-compose-plugin`を使いました。

サンプルプロジェクトとして、
dockerで起動したMockサーバーを使ってAPIアクセスの単体テストを作ってみます。

今回の目的は、`HTTP経由でデータを取得するHTTP Clientの単体テストを行いたい`を解決することです。


成果物

[sugasaki/gradle\-docker\-compose\-test](https://github.com/sugasaki/gradle-docker-compose-test)


# 使うもの

- [IntelliJ Idea](https://www.jetbrains.com/ja-jp/idea/)
- [avast/gradle-docker-compose-plugin](https://github.com/avast/gradle-docker-compose-plugin)
Gradleプラグインに追加することで単体テスト時にDockerを実行
- [Fuel](https://fuel.gitbook.io/documentation/)
Kotlin用 HTTP Client
- [MockServer](https://www.mock-server.com/)
APIテストのためのMock Server


# 概要

HTTPからデータを取得する機能を単体テストする


1. Gracleにgradle-docker-compose-pluginを追加
2. Docker Composeファイルを設置（作成）
3. 単体テストする



# gradle-docker-compose-pluginのメモ

公式サイトを訳したものをメモとして残します。

Gradle環境でのローカル開発と統合テストのためのDocker Composeの使用を簡素化します。


`composeUp`タスクはアプリケーションを起動し、すべてのコンテナが健全になり、公開されているTCPポートがすべて開くまで（アプリケーションの準備が整うまで）待ちます。特定のコンテナの割り当てられたホストとポートを読み込み、dockerCompose.servicesInfosプロパティに格納します。

`composeDown` タスクは、'stopContainers' が 'true' (デフォルト値) に設定されている場合にのみ、アプリケーションを停止し、コンテナを削除します。

`composeDownForced` タスクはアプリケーションを停止し、コンテナを削除します。

`composePull` タスクは、アプリケーションが必要とする画像をプルし、オプションでビルドします。これは例えば、ビルド時間を短縮するためにdockerイメージをキャッシュするCIプラットフォームで有用です。

`composeBuild` タスクはアプリケーションのサービスをビルドします。

`composePush` タスクはサービスのイメージをそれぞれのレジストリ/リポジトリにプッシュします。

`composeLogs` タスクはすべてのコンテナのログを containerLogToDir ディレクトリのファイルに保存します。



## Quick start


### 依存関係に追加

```
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "com.avast.gradle:gradle-docker-compose-plugin:$versionHere"
    }
}

apply plugin: 'docker-compose'
dockerCompose.isRequiredBy(test)
```


### プラグイン指定

Gradle Portal プラグインを使用します (上記のように依存関係を追加する必要はありません)

```
plugins {
  id 'com.avast.gradle.docker-compose' version "$versionHere"
}
```


- docker-compose upはプロジェクトディレクトリで実行されるので、docker-compose.ymlファイルを使用します。
- 提供されたタスク(上の例ではテスト)が新規プロセスを実行する場合、環境変数とJavaシステムのプロパティが提供されます。
  - 環境変数の名前は${serviceName}_HOSTと${serviceName}_TCP_${exposedPort}です。(例: WEB_HOST, WEB_TCP_80)。
  - Javaシステムプロパティの名前は${serviceName}.hostと${serviceName}.tcp.${exposedPort}です。(例: web.host と web.tcp.80)
  - サービスがスケーリングされている場合、サービス名のサフィックスは _1, _2... です (例: WEB_1_HOST と WEB_1_TCP_80, web_1.host と web_1.tcp.80)



## Why to use Docker Compose?


- 自分のコンピュータ上でアプリケーションを実行できるようにしたいし、同僚にも動作するようにしなければなりません。`docker-compose up`を実行するだけで完了します - 例えば、動作中のデータベース。
  
- 自分のコンピュータ上でアプリケーションをテストできるようにしたい - 自分のアプリケーションが開発/テスト環境にデプロイされ、受入れ/エンドツーエンドテストが実行されるまでは待ちたくありません。コンピュータ上でこれらのテストを実行したい - これらのテストの前に docker-compose up を実行することを意味します。




## Why this plugin?

テストの前に `docker-compose up` が呼ばれるようにするのは簡単ですが、このプラグインで解決できる問題がいくつかあります。

- `docker-compose up -d` (detached) を実行した場合、このコマンドはすぐに戻ります。このプラグインは、すべてのコンテナが健全な状態になり、すべてのサービスのエクスポートされた TCP ポートがオープンするまで待機します。

- 健全な状態になるまで待ったり、TCP ポートが開いている状態でタイムアウトした場合 (デフォルトは 15 分です)、関連するサービスのログを表示します。

- docker-compose.yml で公開されているポートの固定値 (例: 8888:80) を指定しないことをお勧めします。ポートを公開する際に固定値を指定しない (80だけを使用する) と、ポートはランダムなフリーポートとして公開されます。このプラグインは、割り当てられたポート (コンテナの IP アドレスも) を読み込み、`dockerCompose.servicesInfo` マップに格納します。

- Linux、Windows、MacでLinuxコンテナを使用している場合と、Windowsコンテナを使用している場合では、細かな違いがあります。このプラグインはこれらの違いを処理してくれるので、 **どの環境でも同じ経験をすることができます。**





# Tips

- dockerCompose.isRequiredBy(anyTask)を任意のタスク、例えばカスタムのintegrationTestタスクに対して呼び出すことができます。

- あるDockerfileがGradleによって生成されたアーティファクトを必要としている場合は、`composeUp.dependOn project(':my-app').distTar`のように、標準的な方法でこの依存関係を宣言することができます。

- `dockerCompose` のすべてのプロパティは意味のあるデフォルト値を持っているので、触る必要はありません。興味のある方は`ComposeSettings.groovy`を参考にしてみてください。

- `dockerCompose.servicesInfos`には実行中のコンテナに関する情報が含まれているので、`composeUp`タスクが終了した後にこのプロパティにアクセスする必要があります。そのため、テストタスクのdoFirstはこのプロパティにアクセスするのに最適な場所です。

- プラグインは`docker-compose.override.yml`ファイルを尊重しますが、`useComposeFiles`でファイルが指定されていない場合に限ります(コマンドラインの動作に準拠します)。

- `ContainerInfo.groovy`をチェックして、コンテナの実行について知ることができます。

- GradleのビルドでDockerホストを決定し（つまりdocker-machine起動）、composeで使用する環境変数DOCKER_HOSTを設定することができます: `dockerCompose { environment.put 'DOCKER_HOST', '192.168.64.9'}`

- `docker-compose`で実行されるサービスが特定のホスト(CirceCI 2.0のようにDockerとは異なる)で実行されている場合は、環境変数`services_host`を使用することができます。この値は、サービスが待ち受けていると予想されるホスト名として使用されます。



# Fuel

割愛します


# MockServer