IntelliJ+Gradle+SpringBoot+JUnit5(jupiter)で新規開発を始めるときの備忘録


※ build.gradleのJUnit用記述を修正しました。誤った情報記載して申し訳ありません。

# はじめに

炭山水です、こんばんわ。

ちょっと自分でもSpringBoot使っていろいろ作ってみようと思うのですが、その下準備としていったん開発が始められそうなところまで持っていく備忘録をまとめました。

IntelliJのインストール方法や、JDKの入れ方とかはほかでいくらでも記事があるのでそちらに譲るとして、IntelliJ + Gradle + SpringBoot + JUnit5(jupiter)の組み合わせだといろいろ躓くので、その辺毎回躓かないために備忘録を残している感じです。

# 前提

- IntelliJのインストールが済んでいること
- JDKのインストールが済んでいること

# こんな人向け

- SpringBoot開発にEclipseやSTSは使ってるけどIntelliJに乗り換えてみたい
- JUnit4で消耗してる

# 環境

- Windows10 Pro
- IntelliJ IDEA 2019.1.3 Community Edition
- OpenJDK : Java12

# 作業手順

## 新規プロジェクトの作成

File > New > Project

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/0a604aa1-b2e9-d9e8-5b90-c22c85fc1d3e.png)

GradleとJavaをチェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/d6236cd2-94d4-3783-8611-12d14ebb0564.png)

GroupIdとArtifactIdは任意でOK

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/d36675b3-9a2f-3ed0-208b-e1250d191c1f.png)

この辺はお好みでいいと思う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/018c3617-6fd4-d47a-5c5c-e7afbe0bb6c1.png)

特に書き換える必要なし

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/e1ee58b3-6041-99df-2b16-db0b31757044.png)

待ちます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/ce0e222b-83b3-2161-0657-93b97701869f.png)

こんな感じになるはず。

## とりあえず適当にテキストを返すControllerを作るまで

### build.gradleの設定

Springを使いたいので、build.gradleを書き換えていきます。


```groovy
plugins {
    id 'java'
}

group 'net.tan3sugarless.clustering-sample'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

```
プロジェクト作成直後はこんな感じになってるはずです。


```groovy
buildscript {
    ext {
        springBootVersion = '2.1.6.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'idea'

group 'net.tan3sugarless.clustering-sample'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'

    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("org.springframework.boot:spring-boot-starter-test")
}

```
buildscript,apply plugin,dependenciesをいじりました。
あと、pluginsを消しています。残してもいいかもしれない…。

### アクセスポイント(Controller)の作成

そしたら実際にWebからアクセスするアクセスポイントとしてControllerクラスが動くようにしていきます。

とりあえず、この時点ではpackageすらないので作っていきます。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/e428a287-04f3-ba05-dec4-99ff054941fd.png)

Projectツリーのsrc/main/javaを右クリックして、New > packageでpackageを作りましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/051af451-6a50-91f9-4a77-f889070c3b43.png)

開いた画面でpackage名を入力します。
※ プロジェクトのartifactIdミスったかも・・・まあいいか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/1820fc40-651d-4071-59e6-f5258a544f07.png)

packageができました。出来上がったpackageをまた右クリック、New > Java Classと開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/f041627f-6356-3e93-6b43-3533f3625cca.png)

開いた画面でまずはApplicationクラスを作ります。Controllerはちょっと待ってね。

```java
package net.tan3sugarless.clusteringsample;

public class ClusteringSampleApplication {
}
```

するとまっさらなクラスが作られます。こいつにSpringのApplicationクラスとしての記述を足していきましょう。

このApplicationクラスを実行することで、これから追加するControllerクラスをはじめ、Webサーバーアプリケーションとしての機能が立ち上がるわけです。

```java
package net.tan3sugarless.clusteringsample;

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

@SpringBootApplication
public class ClusteringSampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ClusteringSampleApplication.class, args);
    }
}

```
こんな感じに書き換えてください。「ClusteringSampleApplication」のところは各自ご自身のクラス名に置き換えてください。

さて、いよいよControllerクラスです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/d8a83971-3358-2d90-372e-9d2d61bd2a97.png)

さらにcontroller packageを先ほどと同じ手順で作ります。別になくてもいいですが、直下にべたべたクラス置くのもね。。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/c0648234-695b-f131-aea7-dad1d8b7e489.png)

で、やはりApplicationクラスと同じ手順で「DemoController」クラスを作りましょう。

```java
package net.tan3sugarless.clusteringsample.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @GetMapping("/demo")
    public String demo(){
        return "Hello SpringBoot demo!";
    }
}

```
作ったクラスはこんな感じにします。とりあえずなんでも返せればいいのでRestControllerで。
もっとまじめにjson返したりもいったんパス。テキストメッセージを表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/6a5c2d75-88d8-0ffe-4012-6f9de51a5064.png)

Controllerができたら、Applicationクラスを右クリックしてRunしてみましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/34fc9afb-3adf-d5d3-f1a9-6b692bfdeaf5.png)

Controllerにstartedと表示されたら立ち上がっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/d26fd5b5-30da-be1a-7678-df91ebfd04c7.png)

ほんとはcurlコマンドとかapi tester使うとカッコいいんだけど、とりあえずはブラウザから

http://localhost:8080/demo

ここにアクセスしてコードに書いたとおりの文字列が表示出来たら成功！

ほんとはlombokとかフツーに使うだろってのも紹介しときたいけどいったん割愛。

## JUnit5(jupiter)を動かす

テストはこまめに書いておきたいので、JUnit5の準備も早めにしておきましょう。

ネットを漁るとJUnit4の情報がまだまだ多いですが、僕はParameterizedTest無しには生きられない体なので、JUnit5(jupiter)を設定します。

基本的にはここ読んでって話だけど、備忘録的に自分でもやってみて書いておきます。

Baeldung | Using JUnit 5 with Gradle
https://www.baeldung.com/junit-5-gradle

### build.gradleの追記

まずJUnitを使えるようにしないといけないので、build gradleに追記します。

```groovy
buildscript {
    ext {
        springBootVersion = '2.1.6.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'idea'

group 'net.tan3sugarless.clustering-sample'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'

    compileOnly "org.projectlombok:lombok:1.18.8"
    testCompileOnly "org.projectlombok:lombok:1.18.8"

    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("org.springframework.boot:spring-boot-starter-test")

    // for JUnit
    testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2'
    testCompile 'org.junit.jupiter:junit-jupiter-params:5.3.2'
    testCompile 'org.junit.jupiter:junit-jupiter-engine:5.3.2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.3.2'
}

// for JUnit
test {
    useJUnitPlatform {
        includeEngines 'junit-jupiter'
    }
}
```

for JUnit とコメント入れたところが足したコードです

### 適当なテストコードを書いてみる

走ったことが確認できればいいので、テスト対象メソッドの作成はさておいて、Assertionだけ見られれば良しとしますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/192a184b-436f-d641-08f0-ccc213294bbb.png)

テスト対象のメソッド作らないのでpackageそろえる意味もないのですが、なんとなくsrc/main/javaと同じpackageをsrc/test/javaにも作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/931f6629-f3b0-fdf3-999c-31fd7629d50b.png)

テストクラスも適当な名前でとりあえず作ります。

```java

package net.tan3sugarless.clusteringsample.controller;

import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

public class DemoTest {

    static Stream<Arguments> demoProvider(){
        return Stream.of(
                Arguments.of(1,1,2),
                Arguments.of(2,2,4)
        );
    }

    @ParameterizedTest
    @MethodSource("demoProvider")
    @DisplayName("Parameterizedテストのデモ")
    void demo(int i, int j, int expected){
        Assertions.assertEquals(expected,i+j);
    }

    @Test
    void fail(){
        Assertions.fail();
    }
}
```

すごく意味のないテストですが、demoなんでご容赦を。

あと、ちゃんと動いてるか見るためにわざとこけさせています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/76d1fd6c-bf4a-cec8-689a-0c8a2973baab.png)

test/javaを右クリックして、Run Test in ...を実行しましょう。テストが全ケース走ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298785/7466acd5-f88c-339e-b41e-cd419f81cce4.png)

ちゃんと想定通りfail()メソッドでコケてくれました。

おしまい。

# おわりに

本当はTestRunnerをGradleから変更するか、成功ケースも確認可能にするかくらいまでやりたかったですが、今日はいったんここまで。

別の機会で解説できればと思いますノシ

Twitterもやってますよろしくね。
( Twitter [@tan3_sugarless](https://twitter.com/tan3_sugarless) )