Edited at

Spring Boot + JUnit5 + Kotlin でテストを書く


更新情報

本記事はSpring Boot 2.1がリリースされる前に記述したものになります。2.1からは各種テストアノテーションに@ExtendWith(SpringExtension.class)を付与する変更が入ったため、@SpringBootTestアノテーションを使用している場合は@ExtendWith(SpringExtension::class)を付与する必要はなくなりました。


はじめに

本投稿ではSpring Bootを用いたプロジェクトにおいて、

どのようにJUnit5を導入するかご説明します。

JUnit5の詳しい記述方法に関して本投稿では触れませんのでご注意ください。

また本投稿では以下の構成を想定しています。

- Spring Boot: 2系

- JUnit5

- Kotlin: 1.2系

- Gradle: 4.6以上


準備

まずはSpring Bootプロジェクトを作成します。

Kotlinでプロジェクトを作成するとbuild.gradleは以下のような記述になるかと思います。

プロジェクト作成時に生成されるbuild.gradle


build.gradle

buildscript {

ext {
kotlinVersion = '1.2.41'
springBootVersion = '2.0.3.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
}
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
compileKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = "1.8"
}
}

repositories {
mavenCentral()
}

dependencies {
compile('org.springframework.boot:spring-boot-starter')
compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
compile("org.jetbrains.kotlin:kotlin-reflect")
testCompile('org.springframework.boot:spring-boot-starter-test')
}



つぎにSpring BootでJUnit5を使用するための設定を記述していきます。

なおGradleはバージョン4.6でJUnit5がサポートされたため、それ以降のバージョンを使用してください。

dependencies以降の記述を以下のように変更します。

dependencies {

compile('org.springframework.boot:spring-boot-starter')
compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
compile("org.jetbrains.kotlin:kotlin-reflect")
testCompile('org.springframework.boot:spring-boot-starter-test') {
exclude module: 'junit' // 1
}
testImplementation('org.junit.jupiter:junit-jupiter-api') // 2
testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine') // 2
}

test {
useJUnitPlatform() // 3
}


  1. spring-boot-starter-testには4系がデフォルトで含まれるため、それを除外します。

  2. junit-jupiter-apiとjunit-jupiter-engineの追加します。

  3. こちらの記述でJUnit5を有効化します。

以上で準備は完了です。


テストコードの作成

例えばJUnit4で書かれた以下のようなテストファイルがあるとします。

import org.junit.Assert

import org.junit.Before
import org.junit.Test
import org.junit.jupiter.api.assertThrows
import org.junit.runner.RunWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner

class Color {
fun getRed(): String = "FF0000"
fun throwException() { throw Exception() }
}

@RunWith(SpringRunner::class)
@SpringBootTest
class ColorTests {

@Before
fun setup() {
// do something
}

@Test
fun getRedTest() {
Assert.assertEquals("FF0000", Color().getRed())
}

@Test
fun throwExceptionTest() {
assertThrows<Exception> {
Color().throwException()
}
}
}

こちらをJUnit5で記述すると以下のようになります。

import org.junit.jupiter.api.Assertions.assertEquals

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit.jupiter.SpringExtension

class Color {
fun getRed(): String = "FF0000"
fun throwException() { throw Exception() }
}

@ExtendWith(SpringExtension::class) // 1
@SpringBootTest
class ColorTests {

@BeforeEach // 2
fun setup() {
// do something
}

@Test
fun getRedTest() {
assertEquals("FF0000", Color().getRed())
}

@Test
fun throwExceptionTest() {
assertThrows<Exception> {
Color().throwException()
}
}
}


  1. JUnit5ではRunnerがExtensionになったため、それに伴う変更です。

  2. JUnit5からいくつかのアノテーションが変更されました。


まとめ

Spring BootでJUnit5を導入する方法を簡単にご紹介しました。

おさらいすると覚えておくべき点は4つです。

1. Gradle4.6以上

2. spring-boot-starter-testから4系を抜く

3. Junit5の依存関係を追加し、useJUnitPlatform()で有効化する

4. テストクラスに付与するアノテーションは@SpringBootTestと以下

@RunWith(SpringRunner::class) // これではなく、

@ExtendWith(SpringExtension::class) // これを書く

なにか間違いなどございましたらご指摘いただけると幸いです。