WSL2でSpringBootとTestcontainersを使う

# この記事の目的
社内での開発はProxyを経由するため様々なツールのProxy設定が面倒で、新規参入者が開発環境を構築するのに手間が掛かる。
この問題に対処するために、Proxy設定済み＆最低限のツールを導入済みの状態のWSL2のイメージを配布し、開発者がそれをインポートすることで開発環境の効率化を目指す。

# 構築する環境のイメージ
以下のツール群が導入済みの状態
* JDK
* Docker
* Maven, Gradle

# 導入の大きな流れ
* WSL2のイメージをインポートし起動する
* IDEAを使えるようにFirewallの設定などを行う
* IDEAのプロジェクトを設定する
* SpringBootとTestcontainersを使ったサンプルアプリを導入する

# 手順詳細
## WSL2のイメージをインポートし起動する

前提として、WSL2自体のインストールは完了しているものとする。
もしも完了していない場合には、MSの公式サイトなどを参考にしてインストールすること。
[公式サイト](https://docs.microsoft.com/ja-jp/windows/wsl/install)

ここでは記載を省略するが、AWSのS3上にイメージを置いてあるので、PresignedURLを払い出して、ユーザーにイメージをダウンロードしてもらう。

### WSL2イメージインポート
対象のイメージをローカルにダウンロードして `PowerShell` から以下のコマンドを実行する。

```powershell
wsl --import {仮想マシン名} {ディスクイメージの配置場所} {イメージの tar ファイル}
```

例
```powershell
wsl --import Ubuntu-20.04_dev_java .\wsl_manual_install\Ubuntu-20.04_dev_java .\ubuntu-20.04_dev_java.tar
```

### 仮想マシンの一覧表示
```powershell
wsl --list --verbose
# 短縮形として、wsl -l -v でもOK
```

### 仮想マシンの起動
```powershell
wsl -d {仮想マシン名}
```

### 仮想マシンの停止
```powershell
wsl --terminate {仮想マシン名}
```

### WSL2 から仮想マシンの登録削除
```powershell
wsl --unregister {仮想マシン名}
```

## IDEAを使えるようにFirewallの設定などを行う
IDEAでWSL2上のJava環境にアクセスするためには以下の手順が必要になる。

:::note info
Firewall設定はWindowsをリブートすると再設定が必要なようだ。
これを永続化する方法は不明（未調査）
:::
### Firewallの設定
https://www.jetbrains.com/help/idea/how-to-use-wsl-development-environment-in-product.html#debugging_system_settings

### WSL2上のファイルをIDEAから開く手順
https://pleiades.io/help/idea/how-to-use-wsl-development-environment-in-product.html#open-a-project-in-wsl

こちらのポイントはpathの指定方法。
キーボードからの入力が案外面倒なので、コピペ用にpathの先頭を記載しておく。
`\\wsl$`

## IDEAのプロジェクトを設定する
WSL2上のJavaプロジェクトは、何故か、File>New>Project from Existing Sourceから開けない（開こうとするとIDEAが落ちる）ので、File>Openで開きます。
このため、開いた後で以下の設定が必要です。

* File>Project Structures... でSDK(JDK）を設定する
* pom.xmlを右クリックして、Add As Maven Projectを選択する

以上により、通常の（Windows上の）プロジェクトと同じ操作感で使用できる。


## SpringBootとTestcontainersを使ったサンプルアプリを導入する

Testee（ターゲットクラス）は、普通のJpaRepositoryである。（特に実装をは追加していない）

```java
package com.example.testcontainers.domain.repository;

import com.example.testcontainers.domain.model.Todo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface TodoRepository extends JpaRepository<Todo, Integer> {
}

```

これのテストクラスは以下のようになる。

```java
package com.example.testcontainers.domain.repository;

import com.example.testcontainers.domain.model.Todo;

import java.util.List;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test; // jupiterの@Testを指定すること！！
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.jdbc.Sql;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
@DataJpaTest(excludeAutoConfiguration = AutoConfigureTestDatabase.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class TodoRepositoryTest {

    @Autowired
    private TodoRepository todoRepository;

    @Test
    @Sql(scripts = "classpath:/scripts/init.sql")
    public void test() {
        List<Todo> todos = todoRepository.findAll();
        Assertions.assertThat(todos.size()).isEqualTo(3);
    }
}

```

テストのプロパティーは以下の様に設定した。
JDBCドライバーはTestcontainerが提供しているクラスを使っている。

MySQLのDockerImageのバージョン（5.7.38）をここで指定しているのが若干気持ち悪いが、時間の関係で一旦これで...

```properties
spring.datasource.url=jdbc:tc:mysql:5.7.38://hostname:port/test?TC_MY_CNF=mysql_conf
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.datasource.username=test
spring.datasource.password=
spring.datasource.sql-script-encoding=utf-8

spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
```

これで、`mvn test`一発で、コンテナでMySQLが勝手に立ち上がってテストが出来るので、かなり楽チンである。

## 課題（または制約）

* WSL2のイメージのサイズがでかい
  これは致し方ないのだが、OSのパッチを当てるとか色々とサイズが大きいがゆえに取り回しが不便ではある。
　Cloud9を使う（VSCodeからつなげられるらしい）とか、Docker使うとかの代替手段も併用したい。 
* WSL2 BackedだとIDEAが若干不安定
  これも致し方ないが、Windows上で直接IDEAを実行するよりも、不安定（起動時に立ち上がらず落ちることがたまにある）なので、VSCodeの方が良いかもしれない。

:::note warn
VSCodeだとCheckStyleが動かないので、これさえ何とかすればIDEAよりも良いかも？
(2022-08-18追記：VSCodeでもCheckStyleは動くことが確認とれました。別途追記します。)
:::

* DB+APIをTestcontainersで稼働させる
  これは私の師匠が目論んでいるので、来週以降で試す（かも）

## ソース
ソースはGitHubに公開しておく。
https://github.com/akiraabe/testcontainers


## 参考記事
以下の記事はめちゃめちゃ参考になった。ありがとうございました！

https://qiita.com/kazuki43zoo/items/588bbfab3db9d6c0199f
https://qiita.com/os1ma/items/f8d3df2c61e16a7c8b20
https://qiita.com/y518gaku/items/c7d4734c5bf6e960606d
https://b1a9idps.com/posts/test-containers/