かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その15 )( JUnit 4 を依存関係から削除する+他3点の気づいた点を変更する )

概要

記事一覧はこちらです。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その14 )( google_checks.xml に Record に関する定義を反映する+bootBuildImage タスクで Java 17 ベースの Docker Image を作成して動作確認する ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Spring Boot を 2.5系にバージョンアップしても JUnit 4 が依存関係に残ることに気づいたので除去します。
    • IntelliJ IDEA で Rebuild Project した時に生成される out ディレクトリが Gradle の clean タスクを実行しても残ることに気づいたので削除されるようにします。
    • Mockito.mockStatic を使用するテストでは try-with-resources 構文を使用してリソースが close されるようにしないといけないことに気づいたので修正します。
    • JDK 17 がサポートされた Lombok 1.18.22 がリリースされていたのでバージョンアップします。

参照したサイト・書籍

  1. How to exclude Gradle dependencies
    https://tomgregory.com/how-to-exclude-gradle-dependencies/

  2. @StandardException annotation for generating exception constructors
    https://github.com/projectlombok/lombok/pull/2702

目次

  1. 依存関係から JUnit 4 を除去する
  2. JUnit 4 のモジュールを利用しているクラスを変更・削除する
    1. src/test/java/ksbysample/common/test/extension/db/TestDataExtension.java
    2. src/test/java/ksbysample/common/test/extension/mail/MailServerExtension.java
    3. src/test/java/ksbysample/common/test/extension/mockmvc/SecurityMockMvcExtension.java
    4. src/test/java/ksbysample/common/test/helper/DescriptionWrapper.java
    5. src/test/groovy/ksbysample/webapp/lending/SampleHelperTest.groovy
  3. clean タスクで out ディレクトリが削除されるようにする
  4. Mockito.mockStatic を呼び出しているテストで try-with-resources 構文を使用してリソースが close されるようにする
  5. Lombok を 1.18.20 → 1.18.22 にバージョンアップする
  6. WebApplicationRuntimeException クラスを Lombok の @StandardException を利用して書き直す
  7. build タスクでエラーが出ないことを確認する

手順

依存関係から JUnit 4 を除去する

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その100 )( Gradle を 6.9.1 → 7.2 へ、Spring Boot を 2.4.10 → 2.5.4 へ、Geb を 4.1 → 5.0 へバージョンアップする2 ) の作業で Spring Boot を 2.5系にバージョンアップしても JUnit 4 が依存関係に残っていることに気づいたので、除去することにします。

今回は個々のモジュールに exclude を記述して除外するのではなく configurations block に exclude を記述する方法を採用します。build.gradle を以下のように変更します。

configurations {
    compileOnly.extendsFrom annotationProcessor

    // annotationProcessor と testAnnotationProcessor、compileOnly と testCompileOnly を併記不要にする
    testAnnotationProcessor.extendsFrom annotationProcessor
    testImplementation.extendsFrom compileOnly

    // JUnit 4 が依存関係に入らないようにする
    all {
        exclude group: "junit", module: "junit"
    }

    // for SpotBugs
    spotbugsStylesheets { transitive = false }
}
  • all { exclude group: "junit", module: "junit" } を追加します。

JUnit 4 のモジュールを利用しているクラスを修正する

src/test/java/ksbysample/common/test/extension/db/TestDataExtension.java

@Component
public class TestDataExtension implements BeforeEachCallback, AfterEachCallback {

    ..........

    @Override
    public void beforeEach(ExtensionContext context) {
        before(new ExtensionContextWrapper(context));
    }

    @Override
    public void afterEach(ExtensionContext context) {
        after(new ExtensionContextWrapper(context));
    }

    ..........
  • extends TestWatcher を削除します。
  • 以下のメソッドを削除します。
    • protected void starting(Description description) { ... }
    • protected void finished(Description description) { ... }

src/test/java/ksbysample/common/test/extension/mail/MailServerExtension.java

@Component
public class MailServerExtension implements BeforeEachCallback, AfterEachCallback {

    private GreenMail greenMail = new GreenMail(new ServerSetup(25, "localhost", ServerSetup.PROTOCOL_SMTP));

    @Override
    public void beforeEach(ExtensionContext context) {
        greenMail.start();
    }

    @Override
    public void afterEach(ExtensionContext context) {
        greenMail.stop();
    }

    ..........
  • extends ExternalResource を削除します。
  • 以下のメソッドを削除します。
    • protected void before() { ... }
    • protected void after() { ... }
  • beforeEach メソッド内の before();greenMail.start(); に変更します。
  • afterEach メソッド内の after();greenMail.stop(); に変更します。

src/test/java/ksbysample/common/test/extension/mockmvc/SecurityMockMvcExtension.java

@Component
@ConditionalOnWebApplication
public class SecurityMockMvcExtension implements BeforeEachCallback {

    ..........

    @Override
    public void beforeEach(ExtensionContext context) {
        // 認証ユーザ用MockMvc ( user = tanaka.taro@sample.com )
        UserDetails userDetailsTanakaTaro = userDetailsService.loadUserByUsername(MAILADDR_TANAKA_TARO);
        this.authTanakaTaro = MockMvcBuilders.webAppContextSetup(this.context)
                .defaultRequest(get("/").with(user(userDetailsTanakaTaro)))
                .apply(springSecurity())
                .build();

        // 認証ユーザ用MockMvc ( user = suzuki.hanako@test.co.jp )
        UserDetails userDetailsSuzukiHanako = userDetailsService.loadUserByUsername(MAILADDR_SUZUKI_HANAKO);
        this.authSuzukiHanako = MockMvcBuilders.webAppContextSetup(this.context)
                .defaultRequest(get("/").with(user(userDetailsSuzukiHanako)))
                .apply(springSecurity())
                .build();

        // 認証ユーザ用MockMvc ( user = ito.aoi@test.co.jp )
        UserDetails userDetailsItoAoi = userDetailsService.loadUserByUsername(MAILADDR_ITO_AOI);
        this.authItoAoi = MockMvcBuilders.webAppContextSetup(this.context)
                .defaultRequest(get("/").with(user(userDetailsItoAoi)))
                .apply(springSecurity())
                .build();

        // 非認証ユーザ用MockMvc
        this.noauth = MockMvcBuilders.webAppContextSetup(this.context)
                .apply(springSecurity())
                .build();
    }

}
  • extends ExternalResource を削除します。
  • before メソッド内のコードを beforeEach メソッドへ移動します。
  • 以下のメソッドを削除します。
    • protected void before() { ... }

src/test/java/ksbysample/common/test/helper/DescriptionWrapper.java

このファイルは使用されなくなったので削除します。

src/test/groovy/ksbysample/webapp/lending/SampleHelperTest.groovy

@RunWith(Enclosed) が記述されていたので削除します。

clean タスクで out ディレクトリが削除されるようにする

build.gradle の clean block を以下のように変更します。

clean {
    doLast {
        rootProject.file("out").deleteDir()
        rootProject.file("src/main/generated").deleteDir()
        rootProject.file("src/test/generated_tests").deleteDir()
    }
}
  • rootProject.file("out").deleteDir() を追加します。

Mockito.mockStatic を呼び出しているテストで try-with-resources 構文を使用してリソースが close されるようにする

src/test/groovy/ksbysample/webapp/lending/SampleHelperTest.groovy で以下のように書いているテストを、

    @SpringBootTest
    static class 異常処理のテスト {

        @Autowired
        private SampleHelper sampleHelper

        @Test
        void "SampleHelper_encryptを呼ぶとRuntimeExceptionをthrowする"() {
            // setup:
            Mockito.mockStatic(BrowfishUtils)
            Mockito.when(BrowfishUtils.encrypt(Mockito.any()))
                    .thenThrow(new NoSuchPaddingException())

            // expect:
            assertThatThrownBy(() -> {
                sampleHelper.encrypt("test")
            }).isInstanceOf(RuntimeException)
        }

    }

try-with-resources 構文を使用してリソースが close されるよう書き直します。

    @SpringBootTest
    static class 異常処理のテスト {

        @Autowired
        private SampleHelper sampleHelper

        @Test
        void "SampleHelper_encryptを呼ぶとRuntimeExceptionをthrowする"() {
            try (MockedStatic mockedBrowfishUtils = Mockito.mockStatic(BrowfishUtils)) {
                // setup:
                Mockito.when(BrowfishUtils.encrypt(Mockito.any()))
                        .thenThrow(new NoSuchPaddingException())

                // expect:
                assertThatThrownBy(() -> {
                    sampleHelper.encrypt("test")
                }).isInstanceOf(RuntimeException)
            }
        }

    }

Lombok を 1.18.20 → 1.18.22 にバージョンアップする

IntelliJ IDEA で build.gradle を見ていたら org.projectlombok:lombok: のところの色が変わっていて、マウスオーバーすると 1.8.22 がリリースされていることが分かりました。Alt+Enter を押すとバージョンも書き替えることも出来ます。この機能、すごい便利じゃないですか。。。

f:id:ksby:20211020062725p:plain

https://projectlombok.org/changelog を見ると v1.18.22 で PLATFORM: JDK17 support added. とのことなので、バージョンアップします。

build.gradle の以下の点を変更します。

dependencies {
    def spockVersion = "2.0-groovy-3.0"
    def jdbcDriver = "org.postgresql:postgresql:42.2.24"
    def domaVersion = "2.49.0"
    def lombokVersion = "1.18.22"
    def errorproneVersion = "2.9.0"

    ..........
  • def lombokVersion = "1.18.20"def lombokVersion = "1.18.22" に変更します。

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。

WebApplicationRuntimeException クラスを Lombok の @StandardException を利用して書き直す

https://projectlombok.org/changelog の v1.18.22 のところを見ると @StandardException というアノテーションが追加されたとの記載があり、https://github.com/projectlombok/lombok/pull/2702 を見ると Exception クラスを継承して作成する時の基本的なコンストラクタを4つ自動生成してくれるとのこと。

便利そうなので WebApplicationRuntimeException クラスを @StandardException を利用して書き直してみます。

src/main/java/ksbysample/webapp/lending/exception/WebApplicationRuntimeException.java は現在以下のように実装していますが、

package ksbysample.webapp.lending.exception;

public class WebApplicationRuntimeException extends RuntimeException {

    @SuppressWarnings("PMD.FieldNamingConventions")
    private static final long serialVersionUID = 3845674924872653036L;

    public WebApplicationRuntimeException() {
        super();
    }

    public WebApplicationRuntimeException(String message) {
        super(message);
    }

    public WebApplicationRuntimeException(String message, Throwable cause) {
        super(message, cause);
    }

    public WebApplicationRuntimeException(Throwable cause) {
        super(cause);
    }

}

@StandardException を利用して書き直すと以下のようになります。@SuppressWarnings("PMD.FieldNamingConventions") も build 時に PMD が警告を出さないことに気づいたので削除します。

package ksbysample.webapp.lending.exception;

import lombok.experimental.StandardException;

import java.io.Serial;

@StandardException
public class WebApplicationRuntimeException extends RuntimeException {

    @Serial
    private static final long serialVersionUID = 3845674924872653036L;

}

build タスクでエラーが出ないことを確認する

最後に clean タスク実行 → Rebuild Project 実行 → build タスクを実行して、"BUILD SUCCESSFUL" のメッセージが出力されることを確認します。

f:id:ksby:20211020072446p:plain

履歴

2021/10/20
初版発行。