SpringBootとJUnit5でMockMvcを使うには

# はじめに

MockMvc を使ったテストプログラムの勉強のためサンプル作りに励んでいましたが、うまく動作せず。エラーの内容を確認しながら試行錯誤するも解決できず。

Spring の Getting Started の記事を見つけて、自分のサンプルと比べてみると、JUnit のバージョンに差異があることに気づく。
紹介されているプログラムは JUnit4 で作成されていた。JUnit5 でMockMvc を利用するには他に必要なことがあるらしい。

- [Testing the Web Layer](https://spring.io/guides/gs/testing-web/)

このサンプルをJUnit5で動かすことに成功したので紹介します。

# 利用したプログラム
Eclipseでサンプルを取得。gs-testing-web-complete から以下のファイルだけ gs-testing-web-initial 利用。

- src/main/java/Application.java
- src/main/java/HomeController.java
- src/test/java/WebLayerTest.java

# pom.xml の修正
Junit5を利用するため以下をdependenciesに追加。

```xml
<dependency>
	<groupId>org.junit.platform</groupId>
	<artifactId>junit-platform-commons</artifactId>
	<version>1.3.1</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.junit.platform</groupId>
	<artifactId>junit-platform-engine</artifactId>
	<version>1.3.1</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.junit.platform</groupId>
	<artifactId>junit-platform-launcher</artifactId>
	<version>1.3.1</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.junit.platform</groupId>
	<artifactId>junit-platform-runner</artifactId>
	<version>1.3.1</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.junit.platform</groupId>
	<artifactId>junit-platform-suite-api</artifactId>
	<version>1.3.1</version>
	<scope>test</scope>
</dependency>

<dependency>
	<groupId>org.junit.jupiter</groupId>
	<artifactId>junit-jupiter-api</artifactId>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.junit.jupiter</groupId>
	<artifactId>junit-jupiter-engine</artifactId>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.junit.jupiter</groupId>
	<artifactId>junit-jupiter-params</artifactId>
	<scope>test</scope>
</dependency>
```

# テストプログラムのJUnit5化

## ①アノテーション変更

```
// 変更前
@RunWith(SpringRunner.class)

// 変更後
@ExtendWith(SpringExtension.class)
```

## ②インポート文の置き換え

アノテーション @Test をJUnit5 に変更するため import 文を全部削除して、Eclipseのショートカットを使って置き換え。

## ③テストコンフィグファイルの作成

これが重要でした。個々のテストクラスで、コンポーネントスキャンしてクラスを参照できるようにしてあげます。

以下に、編集後のプログラムを残します。

# 修正後のJavaプログラム

- src/main/java/hello/Appliation.java (修正なし）

```java
package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
```

- src/main/java/hello/HomeController.java（変更なし）

```java
package hello;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HomeController {

    @RequestMapping("/")
    public @ResponseBody String greeting() {
        return "Hello World";
    }

}
```

- src/test/java/hello/WebLayerTest.java

```java
package hello;

import static org.hamcrest.CoreMatchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;

@ExtendWith(SpringExtension.class)
@WebMvcTest(HomeController.class)
//tag::test[]
public class WebLayerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldReturnDefaultMessage() throws Exception {
        this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("Hello World")));
    }
}
//end::test[]
```

- src/test/java/hello/TestConfig.java

```java

package hello;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({"hello"})
public class TestConfig {
}

```


# 参考サイト

- [Junit5 Test Rest With Springboot And Mockmvc](https://marc-bouvier.github.io/2018/05/23/junit5-test-rest-with-springboot-and-MockMvc/)
- [JUnit 5 User Guide](https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations)
- [Testing the Web Layer](https://spring.io/guides/gs/testing-web/)