Spring boot 1.4 testing with Spock

# はじめに
Spring Boot 1.4が今年の７月末にリリースされましたね。
[こちらの記事](https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4)にも書いてある通り、Spring Boot 1.4ではテストが非常に改善されました！

となると、Spockでテストを書きたくなりますよね！？
ここではSpring Boot 1.4でSpockを使用したテスト方法について解説したいと思います。（2016/12/27現在）

# 概要
ここで解説するのは以下の３つです。

1. Spring Initializrでプロジェクト作成
2. Groovy＆Spock化
3. Spockでテストケースの作成

# 1. Spring Initializrでプロジェクト作成

[Spring Initializr](http://start.spring.io/)にアクセスして、必要なモジュールを入れたアプリケーションを作成しましょう。
私は以下のモジュールを入れました。

* Web
* DevTools
* Lombok

# 2. Groovy＆Spock化

残念ながらSpring InitializrにはGroovy、Spockのモジュールが存在しないので、自分で入れなければいけません。

以下の２つのサイトを参考にすれば問題なく実施できます。

* https://github.com/spockframework/spock-example
* [Spring Boot Reference Guide](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-with-spock)

spock-sampleに従ってpom.xmlを変更すればGroovy、Spock化することができます。
具体的には、`spock-core`のdependencyと`gmavenplus-plugin`を追加します。

SpringでSpockを使うためには、`spock-spring`のdependencyを追加します。

## 注意点！！
ここで気をつけなければならないのがSpock1.0ではまだSpring Boot 1.4のテスト用の新しいアノテーションに対応していないのです…

Spock1.1では対応しますがまだリリースされてません。
現在は[Spockのリリースノート](http://spockframework.org/spock/docs/1.1-rc-2/release_notes.html)にも書いてある通り、最新の1.1-rc-2からアノテーションに対応していますので、それ以降のバージョンを採用します。

## pom.xml
上記を反映したpom.xmlは以下になります。

```
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!-- spock化で追加する部分 -->
		<dependency>
			<groupId>org.spockframework</groupId>
			<artifactId>spock-core</artifactId>
			<version>1.1-groovy-2.4-rc-2</version>
			<scope>test</scope>
		</dependency>
		<!-- Springでspockを使うために追加する部分 -->
		<dependency>
			<groupId>org.spockframework</groupId>
			<artifactId>spock-spring</artifactId>
			<version>1.1-groovy-2.4-rc-2</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>

			<plugin>
				<!-- spock化で追加する部分 -->
				<groupId>org.codehaus.gmavenplus</groupId>
				<artifactId>gmavenplus-plugin</artifactId>
				<version>1.4</version>
				<executions>
					<execution>
						<goals>
							<goal>compile</goal>
							<goal>testCompile</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
```

あとはディレクトリを`src/test/java`から`src/test/groovy`に変更しておいたほうがよいです。

# 3. Spockでテストケースの作成
Spring MVC sliceのテストをここでは書いてみたいと思います。
Spring MVC sliceの方法は`@Controlller`, `@RestController`, `@JsonComponent`に対してテストするときに使用します。

## コード
```
package aha.oretama.jp.controller

import aha.oretama.jp.service.SampleService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.test.web.servlet.MockMvc
import spock.lang.Specification

import static org.mockito.Mockito.*
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*

/**
 * @author aha-oretama
 */
@WebMvcTest
class SampleControllerTest extends Specification {

  @Autowired
  MockMvc mvc

  @MockBean
  SampleService sampleService

  def "GetHello"() {
    setup:
    def name = "aha-oretama"
    when(sampleService.getHello(name)).thenReturn("Hello aha-oretama")

    expect:
    mvc.perform(get("/hello").param("name", name))
            .andExpect(status().isOk())
            .andExpect(content().string("Hello aha-oretama"))
  }
}
```

## 解説
#### Runner
Spockが適切なRunnerを選んでくれるので`@RunWith(SpringRunner.class)`は不要です。

#### WebMvcTest
Spring MVC, Jackson, Gson, Message convertersなどを自動で読みこんで、Auto-Configureしてくれます。
また`@Controller`, `@RestController`, `@JsonComponent` なども読みこみ、Auto-Configureしてくれます。
だけではなく、MockMvcを生成してBean登録もしてくれます。

なので、プログラムする際はWebMvcTestつけとけばOKで、あとは自動でSpring-Boot側がいろいろと面倒みてくれます。

#### MockBean
`@MockBean`をつければ、Spring-Bootが勝手にモック化してくれます。めっちゃ便利。

## サンプル
ここで使用したサンプルはGitHubにあげてあるのでよければ参考にしてくださーい。
https://github.com/aha-oretama/spring-boot-1.4-spock-test-sample

# 最後に

どうでしたか？
Spring Boot 1.4になってからテストが簡単に書けるようになってますし、
それにSpockをあわせることでもっと簡単な記述にできましたね！

Spring Boot 1.4でもどんどんSpockを使っていきましょう！！

P.S.
Spock1.1のリリースが待ち遠しいですねー。