LoginSignup
37
29

More than 3 years have passed since last update.

【Java】Java14×Spring Boot2.3×JUnit5でHelloWorldしたよ〜

Last updated at Posted at 2020-05-29

はじめに

こんにちは!macでSTSの環境構築を行った者です。
今回は「HelloWorldファイルとHelloWorldのテストコードファイルを作成し、jarに保存してmacで実行してみる」ところまで実施しました。
前回同様、Spring徹底入門を参考に進めました。簡単な手順ですが、バージョンのせいかJUnitで実行する辺りやjarにする辺りで思いの外詰まったので記事にしました。
ぜひ俺の屍を越えていってください。

使用環境とバージョン

  • macOS Catalina
  • jdk14.0.1
  • JUnit5
  • Maven 3.6.3_1
  • STS 4.6.1
  • Spring Boot 2.3

Spring Initializrでプロジェクトの雛形を作る

まずSpring Initializrでプロジェクトの雛形を作成します。
Spring InitializrはSpring Bootが提供しているWebサービスです。必要事項をチェックするだけで、Spring Bootプロジェクト作成の基礎となるディレクトリがzip形式でダウンロードできます。また、メインメソッドの雛形があるDemoApplication.javaと、テストコードの雛形があるDemoApplicationTests.javaが、あらかじめ適切なディレクトリ配下に配置されています。

つまり、ダウンロードするだけで今回の作成物の8割は完成します笑

スクリーンショット 2020-05-20 22.49.42.png

前回Mavenで環境構築を行ったので、ProjectはMavenを選びます。
その他、言語やSpringBootのバージョン、Javaのバージョンなど、自分に合ったものを選択し、GENERATEボタンをクリックすると、demo.zipのダウンロードが始まります。

demo.zipを解凍すると、以下のようなMavenプロジェクトが既に作成されています。すごい!めちゃめちゃ簡単じゃないですか!!

スクリーンショット 2020-05-26 0.47.04.png

解凍したdemoファイルは、環境構築した際に作成したworkspaceディレクトリ配下に移動させておくと進めやすいです。
STSを開き、File > Import > Existing Maven Projectsで、先ほど解凍したdemoフォルダを選択すれば、インポートを行えます。

自動的にビルドが走るので、Package Explorerが以下画像のようにパッケージ表示になるまでしばし待ちます。自動で以下のようにならなかったら、メニューバーからProject > Cleanを押下してください。

スクリーンショット 2020-05-26 1.14.17.png

DemoApplication.javaの編集

ダウンロードしたばかりのDemoApplication.javaの中身は以下のようになっているはずです。


package com.example.demo;

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

@SpringBootApplication
public class DemoApplication {

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

}

SpringはMVCモデルのフレームワークです。HelloWorldプロジェクトは最低限の実装で良いので、クライアントからのリクエストを受け取ってレスポンスを返す1、Controller部分のみを実装していきたいと思います。

■DemoApplicationクラスに@Controllerをつける

言わずもがなですが、@Controllerアノテーションをつければ、そのクラスをコントローラーとすることができます。

@RequestMapping@ResponseBodyを付与したメソッドhelloWorld()を作成する

@RequestMapping@ResponseBody、二つのアノテーションを付与することで、戻り値をレスポンスのコンテンツとすることができます。
参考:Spring MVCのコントローラでの戻り値いろいろ


package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@SpringBootApplication
@Controller
public class DemoApplication {

    @RequestMapping("/")
    @ResponseBody
    String helloWorld() {
        return "Hello World!";
    }

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

}

保存して、DemoApplicationを右クリック > Run As > Java Applicationと選択してメインメソッドを実行すると、http://localhost:8080 でハロワできるはずです!やったね!

スクリーンショット 2020-05-26 2.12.34.png

上記以外の書き方でも、コントローラーのアノテーションを@Controllerから@RestControllerに変更すれば、helloWorld()のアノテーションは@RequestMappingのみで動きます。

ただし、アノテーションの組み合わせを間違えるとエラーが発生します(やらかしました)。どうやらHTTPリクエストがアプリケーション側で受け取れていないとこの画面になるようで、DemoApplication.javaをダウンロードしたまんまで実行しても同じ画面になるそうです。

スクリーンショット 2020-05-26 1.38.40.png

DemoApplicationTests.javaの編集

DemoApplication.javaの実装に合わせて、テストコードも編集していきます。以下がダウンロードしたまんまのテストコードです。これに手を加えていきます。


package com.example.demo;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class DemoApplicationTests {

    @Test
    void contextLoads() {
    }

}

@SpringApplicationConfigration@WebIntegrationTestの代わりに@SpringBootTestを付与する

前者2つのアノテーションはSpring Boot 1.4から非推奨になったため、@SpringBootTestに置き換えます。
@SpringBootTest@SpringBootApplicationがついているクラスをテスト用のコンフィグレーションクラスとして認識します。

@RunWith(SpringRunner.class)の代わりに@ExtendWith(SpringExtension.class)を使用する

SpringRunnerはJUnit4のものなので、JUnit5で使用するとその後のjar作成時にビルドがうまく通らなくなりました…
JUnit5では@RunWithアノテーション自体が@ExtendWithに置き換えられていたので、そちらに変更しました。JUnit5 @RunWith

@LocalServerPortでポート番号を取得する

Spring Boot 1.3以前では@Value(“${local.server.port}”)で取得していたポート番号ですが、1.4以降@LocalServerPortがショートカットとして追加されています。2.3だと@Valueでポート番号を取得しようとすると以下のエラーが発生して、テスト実行ができませんでした。。

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.example.demo.DemoApplicationTests': Unsatisfied dependency expressed through field 'port';
nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; 
nested exception is java.lang.NumberFormatException: For input string: "${local.server.port"

■assertThatメソッドはorg.junit.Assert.assertThatではなくorg.hamcrest.MatcherAssert.assertThatを使用する

JUnitのassertThatは非推奨と出て、deprecatedを許容するアノテーション@SuppressWarnings(“deprecated”)を付与してもうまくjarのビルドができませんでした…(上記以外が原因かもです)
代わりに、hamcrestのassertThatを使用しました。

最終的なテストコードは以下のようになりました。


package com.example.demo;

import static org.hamcrest.CoreMatchers.is;

import static org.hamcrest.MatcherAssert.assertThat;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DemoApplicationTests {

    TestRestTemplate restTemplate = new TestRestTemplate();

    @LocalServerPort
    int port;

    @Test
    public void testHello() {
        assertThat(restTemplate.getForObject("http://localhost:" + port, String.class), is("Hello World!"));
    }

}

DemoApplicationTests.javaを右クリック > Run As > JUnit Testでテストコードが実行できます。JUnitパネルに以下のように表示されれば、テスト成功です!

スクリーンショット 2020-05-26 3.26.19.png

上記テストコードかDemoApplication.javaのどちらかの"Hello World!"部分を別の言葉に変えて、ちゃんとテストが失敗するかも確認してみてください。

スクリーンショット 2020-05-26 3.28.54.png

実行可能jarを作成する

ここまでの工程で、既にSpring プロジェクトのHelloWorldは出来上がっています。しかし、実際にjarにしてみると、コンパイルやビルドがうまくいかないことに気づけるので、やっておくと吉です!

jarを作成する手順を説明していきます。

①macのターミナルから、ワークスペース配下のdemoディレクトリまで移動する

cd ~/Users/xxx/workspace/demo

②実行可能jarを作成するMavenコマンドを実行する

./mvnw clean package

STS上ではHelloWorldもテストもうまく行っていたとしても、ここでエラーが出ることもあります(自分です)
自分はここで@RunWithが使えないことを知りました。

スクリーンショット 2020-05-26 3.40.11.png

うまくいった場合は、下図のようにBUILD SUCCESSが表示されます。

スクリーンショット 2020-05-26 3.46.31.png

③jarを実行する

無事にビルドが成功したら、demo/target 配下に「demo-0.0.1-SNAPSHOT.jar」ができているはずです。末尾にoriginalとついていない方を実行します。

java -jar /Users/xxx/workspace/demo/target/demo-0.0.1-SNAPSHOT.jar

以下のようにSpringが立ち上がれば成功です! http://localhost:8080 で同じようにHello World!が表示できます。

スクリーンショット 2020-05-26 3.52.32.png

おわりに

冒頭に記した通り、Spring徹底入門を読みながら実施しましたが、ただのHelloWorldを作る際に、同じJavaやIDEでも、バージョンが違うだけでこんなに違うんだなと驚きました…バージョン大事と言われる理由が分かりました…
せっかく雛形を作成したので、次回は簡単にアプリを作成して、テストコードも書いてみたいと思います!

お読みいただきありがとうございました!
ここ違うかもよ〜、という箇所ありましたら、例の如く、そ〜っと教えてください…!


  1. Spring MVCの細かな説明は省きますが、正確にはコントローラーの前にあるフロントコントローラーというサーブレットが、リクエストを受け取ってレスポンスを返しています。ここはフレームワークに任せるため、開発者はコントローラーのみ実装します。 

37
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
29