かんがるーさんの日記

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

IntelliJ IDEA を 2021.2.2 → 2021.2.3 へ、Git for Windows を 2.33.0.2 → 2.33.1 へバージョンアップ

IntelliJ IDEA を 2021.2.2 → 2021.2.3 へバージョンアップする

IntelliJ IDEA の 2021.2.3 がリリースされているのでバージョンアップします。

※ksbysample-webapp-lending プロジェクトを開いた状態でバージョンアップしています。

  1. IntelliJ IDEA のメインメニューから「Help」-「Check for Updates...」を選択します。

  2. IntelliJ IDEA and Plugin Updates」ダイアログが表示されます。右下に「Update and Restart」ボタンが表示されていますので、「Update and Restart」ボタンをクリックします。

    f:id:ksby:20211019215125p:plain

  3. Plugin の update も表示されました。このまま「Update」ボタンをクリックします。

    f:id:ksby:20211019215212p:plain

  4. Patch がダウンロードされて IntelliJ IDEA が再起動します。

  5. IntelliJ IDEA が起動すると画面下部に「Indexing」のメッセージが表示されますので、終了するまで待機します(今回はかなり時間がかかりました)。

  6. IntelliJ IDEA のメインメニューから「Help」-「About」を選択し、2021.2.3 へバージョンアップされていることを確認します。

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

    f:id:ksby:20211019221231p:plain

  8. Project Tool Window で src/test でコンテキストメニューを表示して「More Run/Debug」-「Run 'All Tests' with Coverage」を選択し、テストが全て成功することを確認します。

    f:id:ksby:20211019221651p:plain

Git for Windows を 2.33.0.2 → 2.33.1 へバージョンアップする

Git for Windows の 2.33.1 がリリースされていたのでバージョンアップします。

  1. https://gitforwindows.org/ の「Download」ボタンをクリックして Git-2.33.1-64-bit.exe をダウンロードします。

  2. Git-2.33.1-64-bit.exe を実行します。

  3. 「Git 2.33.1 Setup」ダイアログが表示されます。インストーラーの画面を一通り見たいので「Only show new options」のチェックを外してから [Next >] ボタンをクリックします。

  4. 「Select Components」画面が表示されます。「Git LFS(Large File Support)」だけチェックした状態で [Next >]ボタンをクリックします。

  5. 「Choosing the default editor used by Git」画面が表示されます。「Use Vim (the ubiquitous text editor) as Git's default editor」が選択された状態で [Next >]ボタンをクリックします。

  6. 「Adjusting the name of the initial branch in new repositories」画面が表示されます。「Let Git decide」が選択されていることを確認後、[Next >]ボタンをクリックします。

  7. 「Adjusting your PATH environment」画面が表示されます。中央の「Git from the command line and also from 3rd-party software」が選択されていることを確認後、[Next >]ボタンをクリックします。

  8. 「Choosing the SSH executable」画面が表示されます。「Use bundled OpenSSL」が選択されていることを確認後、[Next >]ボタンをクリックします。

  9. 「Choosing HTTPS transport backend」画面が表示されます。「Use the OpenSSL library」が選択されていることを確認後、[Next >]ボタンをクリックします。

  10. 「Configuring the line ending conversions」画面が表示されます。一番上の「Checkout Windows-style, commit Unix-style line endings」が選択されていることを確認した後、[Next >]ボタンをクリックします。

  11. 「Configuring the terminal emulator to use with Git Bash」画面が表示されます。「Use Windows'default console window」が選択されていることを確認した後、[Next >]ボタンをクリックします。

  12. 「Choose the default behavior of git pull」画面が表示されます。「Default (fast-forward or merge)」が選択されていることを確認した後、[Next >]ボタンをクリックします。

  13. 「Choose a credential helper」画面が表示されます。「None」が選択されていることを確認した後、[Next >]ボタンをクリックします。

  14. 「Configuring extra options」画面が表示されます。「Enable file system caching」だけがチェックされていることを確認した後、[Next >]ボタンをクリックします。

  15. 「Configuring experimental options」画面が表示されます。何もチェックせずに [Install]ボタンをクリックします。

  16. インストールが完了すると「Completing the Git Setup Wizard」のメッセージが表示された画面が表示されます。中央の「View Release Notes」のチェックを外した後、[Next >]ボタンをクリックしてインストーラーを終了します。

  17. コマンドプロンプトを起動して git --version を実行し、git のバージョンが git version 2.33.1.windows.1 になっていることを確認します。

    f:id:ksby:20211019222725p:plain

  18. 特に問題はないようですので、2.33.1 で作業を進めたいと思います。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その104 )( Checkstyle を 8.32 → 9.0.1 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その103 )( Eclipse Adoptium OpenJDK(Eclipse Temurin)を 11.0.12+7 → 17+35 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Checkstyle を 8.32 → 9.0.1 へバージョンアップします。

参照したサイト・書籍

目次

  1. Checkstyle を 8.32 → 9.0.1 へバージョンアップする

手順

Checkstyle を 8.32 → 9.0.1 へバージョンアップする

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

checkstyle {
    configFile = file("${rootProject.projectDir}/config/checkstyle/google_checks.xml")
    toolVersion = "9.0.1"
    sourceSets = [project.sourceSets.main]
}
  • toolVersion = "8.32"toolVersion = "9.0.1" に変更します。

https://github.com/ksby/ksbysample-webapp-lending/blob/master/config/checkstyle/google_checks.xml をコピーして config/checkstyle/google_checks.xml に上書きします。

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

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると checkstyleMain タスクで警告が 10件出力されました。全て Javadoc コメントがありません。 [MissingJavadocType] で @interface と enum のクラスコメントがない箇所で出力されていたので、警告が出た箇所に Javadoc のコメントを追加します。

f:id:ksby:20211019025912p:plain

再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると今度は警告なしで "BUILD SUCCESSFUL" が出力されました。

f:id:ksby:20211019031530p:plain

履歴

2021/10/19
初版発行。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その103 )( Eclipse Adoptium OpenJDK(Eclipse Temurin)を 11.0.12+7 → 17+35 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その102 )( SpotBugs を 4.0.2 → 4.4.1 へ、PMD を 6.23.0 → 6.39.0 へ、error-prone を 2.3.4 → 2.9.0 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Eclipse Adoptium OpenJDK(Eclipse Temurin)を 11.0.12+7 → 17+35 へバージョンアップします。

参照したサイト・書籍

  1. Internal JDK Elements Strongly Encapsulated in JDK 17
    https://www.infoq.com/news/2021/06/internals-encapsulated-jdk17/

  2. How to avoid "Sharing is only supported for boot loader classes because bootstrap classpath has been appended" warning during debug with Java 11?
    https://newbedev.com/how-to-avoid-sharing-is-only-supported-for-boot-loader-classes-because-bootstrap-classpath-has-been-appended-warning-during-debug-with-java-11

目次

  1. Eclipse Adoptium OpenJDK(Eclipse Temurin)を 11.0.12+7 → 17+35 へバージョンアップする
  2. configureChromeDriverBinary タスクで java.lang.reflect.InvocationTargetException が発生してタスクが失敗する原因を調査する。。。が、対応方法が分からないので com.github.erdi.webdriver-binaries Plugin を外す
  3. test タスクで Caused by: org.modelmapper.internal.ErrorsException ... が発生するので ModelMapper を最新バージョンに上げる

手順

Eclipse Adoptium OpenJDK(Eclipse Temurin)を 11.0.12+7 → 17+35 へバージョンアップする

IntelliJ IDEA のメインメニューから「File」-「Project Structure...」を選択し、「Project Structure」ダイアログが表示されたら「Project SDK」で「17+35」を選択して「OK」ボタンをクリックします。

f:id:ksby:20211015223606p:plain

メイン画面に戻ると画面右下に「Indexing...」の表示が出るので、終了するまで待ちます。

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

sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
  • JavaVersion.VERSION_11JavaVersion.VERSION_17 に変更します。

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

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると configureChromeDriverBinary タスクで失敗して BUILD FAILED が出力されました。

f:id:ksby:20211015225835p:plain

  • compileTestJava タスクで以下の WARNING が出力される。
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by edu.umd.cs.findbugs.ba.jsr305.TypeQualifierValue (file:/C:/Users/root/.gradle/caches/modules-2/files-2.1/com.github.spotbugs/spotbugs/4.4.1/d50cf49af9b5074d5ab3d0f89889d753623f341e/spotbugs-4.4.1.jar)
WARNING: Please consider reporting this to the maintainers of edu.umd.cs.findbugs.ba.jsr305.TypeQualifierValue
WARNING: System::setSecurityManager will be removed in a future release
  • configureChromeDriverBinary タスクで java.lang.reflect.InvocationTargetException が発生してタスクが失敗する。
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':configureChromeDriverBinary'.
> java.lang.reflect.InvocationTargetException

compileTestJava タスクの WARNING は SpotBugs が内部で System::setSecurityManager を呼び出しているのが原因のようなので、特に対応はせずにこのままとします。

ただし build.gradle を https://github.com/ksby/ksbysample-webapp-lending のものと比較して変更したい点があったので、以下のように変更します。

configurations {
    compileOnly.extendsFrom annotationProcessor

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

    // for SpotBugs
    spotbugsStylesheets { transitive = false }
}

..........

dependencies {
    ..........

    // for SpotBugs
    spotbugs(configurations.spotbugsPlugins.dependencies)
    annotationProcessor("com.github.spotbugs:spotbugs-annotations:${spotbugs.toolVersion.get()}")
    spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.11.0")

    ..........
}
  • configurations block の以下の点を変更します。
    • developmentOnly を削除します。
    • runtimeClasspath { extendsFrom developmentOnly }compileOnly.extendsFrom annotationProcessor に変更します。
  • dependencies block の以下の点を変更します。
    • compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugs.toolVersion.get()}")annotationProcessor("com.github.spotbugs:spotbugs-annotations:${spotbugs.toolVersion.get()}") に変更します。

configureChromeDriverBinary タスクで java.lang.reflect.InvocationTargetException が発生してタスクが失敗する原因を調査する。。。が、対応方法が分からないので com.github.erdi.webdriver-binaries Plugin を外す

build 時に --debug --stacktrace オプションを付けて実行し直してみます。

IntelliJ IDEA のメインメニューから「Run」-「Edit Configurations...」を選択して「Run/Debug Configurations」ダイアログを表示した後、「Gradle」-「boot-npm-geb-sample [build]」を選択後、画面右側の「Run」に --debug --stacktrace を追加します。

f:id:ksby:20211015234017p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると Caused by: java.lang.IllegalAccessException: module jdk.proxy12 does not open jdk.proxy12 to unnamed module @1b604f19 が出力されました。

f:id:ksby:20211015234832p:plain

VM options に --add-opens=jdk.proxy12/jdk.proxy12=ALL-UNNAMED を指定してみます。

f:id:ksby:20211015235358p:plain f:id:ksby:20211016000107p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると Caused by: java.lang.IllegalAccessException: module jdk.proxy4 does not open jdk.proxy4 to unnamed module @cb5822 が出力されたので、

f:id:ksby:20211016000636p:plain

VM options に --add-opens=jdk.proxy4/jdk.proxy4=ALL-UNNAMED を追加します。

f:id:ksby:20211016000831p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行しましたが、前と同じ Caused by: java.lang.IllegalAccessException: module jdk.proxy4 does not open jdk.proxy4 to unnamed module @cb5822 が出力されます。

f:id:ksby:20211016001405p:plain

これは Plugin の Java 17 対応待ちでしょうか。。。 対応方法が分からないので、今回は com.github.erdi.webdriver-binaries Plugin を外すことにします。

build.gradle で com.github.erdi.webdriver-binaries Plugin に関する記述をコメントアウトします。

plugins {
    id "java"
    id "groovy"
    id "eclipse"
    id "idea"
    id "org.springframework.boot" version "2.5.5"
    id "io.spring.dependency-management" version "1.0.11.RELEASE"
    id "net.ltgt.errorprone" version "2.0.2"
    id "checkstyle"
    id "com.github.spotbugs" version "4.7.7"
    id "pmd"
    id "com.github.node-gradle.node" version "3.1.1"
    id "com.gorylenko.gradle-git-properties" version "2.3.1"
// Java 17 で build タスクを実行すると java.lang.reflect.InvocationTargetException が発生し、
// 対応方法が不明なのでコメントアウトする
//    id "com.github.erdi.webdriver-binaries" version "2.6"
    id "org.seasar.doma.codegen" version "1.4.1"
}

..........

// Java 17 で build タスクを実行すると java.lang.reflect.InvocationTargetException が発生し、
// 対応方法が不明なのでコメントアウトする
//// https://github.com/webdriverextensions/webdriverextensions-maven-plugin-repository/blob/master/repository-3.0.json 参照
//webdriverBinaries {
//    chromedriver {
//        version = "94.0.4606.41"
//        architecture = "X86"
//        fallbackTo32Bit = true
//    }
//    geckodriver {
//        version = "0.29.1"
//        architecture = "X86_64"
//    }
//}
def drivers = ["chrome", "firefox"]
..........

またこのままでは WebDriver を認識できず gebTest タスクが成功しないので、src/test/resources/GebConfig.groovy の System.setProperty("webdriver.~ から始まる2行のコメントアウトを解除します。

System.setProperty("webdriver.gecko.driver", "D:/geckodriver/0.30.0/geckodriver.bat")
System.setProperty("webdriver.chrome.driver", "D:/chromedriver/94.0.4606.61/chromedriver.exe")
driver = {
    ChromeOptions chromeOptions = new ChromeOptions()
    new ChromeDriver(chromeOptions)
//    FirefoxOptions firefoxOptions = new FirefoxOptions()
//    new FirefoxDriver(firefoxOptions)
}
..........

build タスクに追加したオプションは全て削除します。

test タスクで Caused by: org.modelmapper.internal.ErrorsException ... が発生するので ModelMapper を最新バージョンに上げる

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、今度は test タスクでテストが大量に失敗しました。

f:id:ksby:20211017093537p:plain

失敗したテストでは Caused by: org.modelmapper.internal.ErrorsException at Errors.java:254 と出力されていました。

build.gradle では implementation("com.github.rozidan:modelmapper-spring-boot-starter:2.3.1") を指定するだけで ModelMapper のバージョンは明記しておらず、依存関係にある ModelMapper のバージョンを確認したところ 2.3.0 でしたので、最新バージョンの 2.4.4 を依存関係に追加してみることにします。

f:id:ksby:20211017094122p:plain

build.gradle に implementation("org.modelmapper:modelmapper:2.4.4") を追加します。

dependencies {
    ..........

    // dependency-management-plugin によりバージョン番号が自動で設定されないもの、あるいは最新バージョンを指定したいもの
    ..........
    implementation("com.github.rozidan:modelmapper-spring-boot-starter:2.3.1")
    implementation("org.modelmapper:modelmapper:2.4.4")
    implementation("com.google.guava:guava:31.0.1-jre")
    ..........

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

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" が出力されました。

f:id:ksby:20211017095358p:plain

OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended のメッセージは test タスクの jvmArgs に -Xshare:off オプションを指定すれば出力されなくなりますが、今のままにします。

gebTest タスクも問題ありませんでした。

f:id:ksby:20211017101430p:plain

履歴

2021/10/17
初版発行。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その102 )( SpotBugs を 4.0.2 → 4.4.1 へ、PMD を 6.23.0 → 6.39.0 へ、error-prone を 2.3.4 → 2.9.0 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その101 )( Spring Boot を 2.5.4 → 2.5.5 へバージョンアップするが、Eclipse Adoptium OpenJDK(Eclipse Temurin)を 11.0.12+7 → 17+35 へバージョンアップするのは一旦諦める ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。

参照したサイト・書籍

目次

  1. SpotBugs を 4.0.2 → 4.4.1 へバージョンアップする
  2. PMD を 6.23.0 → 6.39.0 へバージョンアップする
  3. error-prone を 2.3.4 → 2.9.0 へバージョンアップする

手順

SpotBugs を 4.0.2 → 4.4.1 へバージョンアップする

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

plugins {
    ..........
    id "com.github.spotbugs" version "4.7.7"
    ..........
}

..........

spotbugs {
    toolVersion = "${spotbugs.toolVersion.get()}"
    ignoreFailures = true
    spotbugsTest.enabled = false
    excludeFilter = file("${rootProject.projectDir}/config/spotbugs/exclude.xml")
}
spotbugsMain {
    reports {
        html {
            enabled = true
        }
    }
}

..........

dependencies {
    ..........

    // for SpotBugs
    spotbugs(configurations.spotbugsPlugins.dependencies)
    annotationProcessor("com.github.spotbugs:spotbugs-annotations:${spotbugs.toolVersion.get()}")
    spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.11.0")

    ..........
}
  • plugins block の以下の点を変更します。
    • id "com.github.spotbugs" version "4.0.8"id "com.github.spotbugs" version "4.7.7"
    • プラグインのバージョンを 4.7.7 にすることで SpotBugs のバージョンが 4.4.1 になります。SpotBugs version mapping 参照。
  • spotbugs block の以下の点を変更します。
    • toolVersion = "4.0.2"toolVersion = "${spotbugs.toolVersion.get()}"
    • excludeFilter = file("${rootProject.projectDir}/config/spotbugs/exclude.xml") を追加します。
  • spotbugsMain block の以下の点を変更します。
    • stylesheet = "color.xsl" を削除します。
  • dependencies block の以下の点を変更します。
    • def spotbugsVersion = "4.0.2" を削除します。
    • 以下の行を削除します。
      • compileOnly("com.github.spotbugs:spotbugs:${spotbugsVersion}") { exclude group: "pull-parser", module: "pull-parser" }
      • compileOnly("net.jcip:jcip-annotations:1.0")
      • compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}")
      • testImplementation("com.google.code.findbugs:jsr305:3.0.2")
      • spotbugsStylesheets("com.github.spotbugs:spotbugs:${spotbugsVersion}")
    • 以下の行を追加します。
      • spotbugs(configurations.spotbugsPlugins.dependencies)
      • compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugs.toolVersion.get()}")
    • spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.10.1")spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.11.0")

config ディレクトリの下に spotbugs ディレクトリを新規作成し、https://github.com/ksby/ksbysample-webapp-lending/blob/master/config/spotbugs/exclude.xml をコピーします。

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

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20211013083447p:plain

PMD を 6.23.0 → 6.39.0 へバージョンアップする

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

pmd {
    toolVersion = "6.39.0"
    sourceSets = [project.sourceSets.main]
    ignoreFailures = true
    consoleOutput = true
    ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml")
    ruleSets = []
}
  • toolVersion = "6.23.0"toolVersion = "6.39.0" に変更します。

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

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると PMD で警告が出ました。

f:id:ksby:20211013221405p:plain

レポートファイルを開くと警告は全部で 3種類、7箇所でした。

f:id:ksby:20211013221620p:plain

Logger calls should be surrounded by log level guards.https://ksby.hatenablog.com/entry/2021/09/03/211111#2-1 で対応したように config/pmd/pmd-project-rulesets.xml に設定を追加して、trace, debug のログ出力だけこのチェックが実行されるようにします。

    <rule ref="category/java/bestpractices.xml">
        <!-- CommentRequired はここでは exclude し、下で別途定義する -->
        <exclude name="GuardLogStatement"/>
    </rule>
    <rule ref="category/java/bestpractices.xml/GuardLogStatement">
        <properties>
            <property name="logLevels" value="trace,debug"/>
            <property name="guardsMethods" value="isTraceEnabled,isDebugEnabled"/>
        </properties>
    </rule>

The initializer for variable 'selectOptions' is never used (overwritten on lines 22 and 24)SelectOptions selectOptions = null;SelectOptions selectOptions; に変更します。

        SelectOptions selectOptions;
        if (countFlg) {
            selectOptions = SelectOptions.get().offset(offset).limit(limit).count();
        } else {
            selectOptions = SelectOptions.get().offset(offset).limit(limit);
        }

The method 'checkTelAndEmail(boolean, String, String, String, String, Errors)' has a cognitive complexity of 20, current threshold is 15 は InquiryInput02FormValidator#checkTelAndEmail のメソッドが複雑なので警告が出ているのですが、今回はメソッドに @SuppressWarnings("PMD.CognitiveComplexity") を付与して警告が出ないようにします。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20211013230258p:plain

error-prone を 2.3.4 → 2.9.0 へバージョンアップする

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

plugins {
    ..........
    id "net.ltgt.errorprone" version "2.0.2"
    ..........
}

..........

dependencies {
    ..........
    def errorproneVersion = "2.9.0"
    ..........

    // for Error Prone ( http://errorprone.info/ )
    errorprone("com.google.errorprone:error_prone_core:${errorproneVersion}")
    compileOnly("com.google.errorprone:error_prone_annotations:${errorproneVersion}")
  • plugins block の以下の点を変更します。
    • id "net.ltgt.errorprone" version "1.1.1"id "net.ltgt.errorprone" version "2.0.2"
  • dependencies block の以下の点を変更します。
    • def errorproneVersion = "2.3.4"def errorproneVersion = "2.9.0"

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

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると compileJava タスクで大量にエラーが出ました。1つずつ解消します。

f:id:ksby:20211013232627p:plain

https://errorprone.info/bugpattern/SameNameButDifferentLombok の @Slf4j、@Data アノテーションを付与している箇所で出力されていました。build.gradle を変更して出力されないようにします。https://ksby.hatenablog.com/entry/2021/03/03/210210#2-1 参照。

[compileJava, compileTestGroovy, compileTestJava]*.options*.encoding = "UTF-8"
[compileJava, compileTestGroovy, compileTestJava]*.options*.compilerArgs = ["-Xlint:all,-options,-processing,-path"]
tasks.withType(JavaCompile).configureEach {
    options.errorprone {
        disableWarningsInGeneratedCode = true
        disable("SameNameButDifferent")
    }
}
  • disable("SameNameButDifferent") を追加します。

https://google.github.io/styleguide/javaguide.html#s7.1.3-javadoc-block-tagsJavadoc で @throws、@return の説明文を記述していなかったのが原因でした。@throws、@return に説明文を追加します。https://ksby.hatenablog.com/entry/2020/08/20/002645#2-1 参照。

https://google.github.io/styleguide/javaguide.html#s7.2-summary-fragmentJavadoc に summary fragment がない箇所で出力されていました。summary fragment を記述します。What is a Javadoc summary fragment? 参照。

https://errorprone.info/bugpattern/ReturnValueIgnored は flatMap メソッドの戻り値を元のメソッドで使用していないことが原因でした。@SuppressWarnings("ReturnValueIgnored") を付与してエラーにならないようにします。https://ksby.hatenablog.com/entry/2021/09/04/205832#2-1 参照。

https://errorprone.info/bugpattern/InvalidInlineTagJavadoc{@Clob} と記述していた箇所で出力されていました。{@link Clob} のように修正します。

以上で error-prone が出力しているエラー・警告に対応したので再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行したところ、今度は PMD が 1種類、3箇所で警告を出力していました。

f:id:ksby:20211014001705p:plain

Comment is too large: Too many linesJavadoc の行数が 6行を超えていると出力されていました。https://github.com/ksby/ksbysample-webapp-lending/blob/master/config/pmd/pmd-project-rulesets.xml を見たところ、こちらでは <exclude name="CommentSize"/> を記述してチェックしないようにしていたので、このファイルをコピーすることにします。

再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20211014003932p:plain

履歴

2021/10/14
初版発行。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その101 )( Spring Boot を 2.5.4 → 2.5.5 へバージョンアップするが、Eclipse Adoptium OpenJDK(Eclipse Temurin)を 11.0.12+7 → 17+35 へバージョンアップするのは一旦諦める )

概要

記事一覧はこちらです。

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 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • まず JDK 11 のまま、まずは Spring Boot を 2.5.4 → 2.5.5 へバージョンアップします。
    • その後に Eclipse Adoptium OpenJDK(Eclipse Temurin)を 11.0.12+7 → 17+35 へバージョンアップします。。。が、今回は一旦諦めます。

参照したサイト・書籍

目次

  1. Spring Boot を 2.5.4 → 2.5.5 へバージョンアップする
  2. Eclipse Adoptium OpenJDK(Eclipse Temurin) を 11.0.12+7 → 17+35 へバージョンアップする。。。のは一旦諦める

手順

Spring Boot を 2.5.4 → 2.5.5 へバージョンアップする

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

buildscript {
    ext {
        group "ksbysample"
        version "2.5.5"
    }
    repositories {
        mavenCentral()
        gradlePluginPortal()
    }
    dependencies {
        // for doma-codegen-plugin
        classpath "com.h2database:h2:1.4.200"
    }
}

plugins {
    id "java"
    id "groovy"
    id "eclipse"
    id "idea"
    id "org.springframework.boot" version "2.5.5"
    id "io.spring.dependency-management" version "1.0.11.RELEASE"
    id "net.ltgt.errorprone" version "1.1.1"
    id "checkstyle"
    id "com.github.spotbugs" version "4.0.8"
    id "pmd"
    id "com.github.node-gradle.node" version "3.1.1"
    id "com.gorylenko.gradle-git-properties" version "2.3.1"
    id "com.github.erdi.webdriver-binaries" version "2.6"
    id "org.seasar.doma.codegen" version "1.4.1"
}

Spring Boot 2.5.5 へのバージョンアップとして以下の点を変更します。

  • buildscript block の以下の点を変更します。
    • version "2.5.4"version "2.5.5"
  • plugins block の以下の点を変更します。
    • id "org.springframework.boot" version "2.5.4"id "org.springframework.boot" version "2.5.5"

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

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると test タスクで大量にテストが失敗しました。

f:id:ksby:20211012150450p:plain

失敗したテストを確認すると、全てのテストで Caused by: org.xml.sax.SAXNotRecognizedException at Driver.java:178 が出力されてました。

InquiryMailHelperTest > 全ての項目に値がセットされている場合のテスト FAILED
    java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
        Caused by: java.lang.IllegalStateException at LoggingApplicationListener.java:328
            Caused by: java.lang.IllegalStateException at LogbackLoggingSystem.java:168
                Caused by: ch.qos.logback.core.joran.spi.JoranException at SaxEventRecorder.java:89
                    Caused by: org.xml.sax.SAXNotRecognizedException at Driver.java:178

失敗しているテストを 1つ IntelliJ IDEA から実行すると同様に失敗して、

f:id:ksby:20211012151457p:plain

この時出力されているログを見ると以下の出力があり、

..........
15:07:38,542 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
15:07:38,542 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
15:07:38,543 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/D:/project-springboot/ksbysample-boot-miscellaneous/boot-npm-geb-sample/out/test/resources/logback.xml]
15:07:38,706 |-ERROR in ch.qos.logback.core.joran.event.SaxEventRecorder@44c79f32 - Parser configuration error occurred org.xml.sax.SAXNotRecognizedException: unrecognized feature http://xml.org/sax/features/external-general-entities
..........

out/test/resources/logback.xml に問題がある模様。ファイルを開いてみると以下の内容でした。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--
        Geb+Spock で Firefox を headless モードで動かした時に大量に以下の DEBUG ログ
        が出力されるのを抑制するために作成しているファイルである。ファイルがあればログを抑
        制できるので、特に logger の定義は記述していない。

        [Forwarding ... on session ... to remote] DEBUG org.apache.http
     -->
</configuration>

実際のファイルは src/test/resources/logback.xml なので、このファイルを削除してみます。

再び clean タスク実行。。。してみましたが、out ディレクトリを削除してくれないことに気づきました。clean タスクで out ディレクトリと、ついでに src/main/generated、src/test/generated_tests ディレクトリを削除するよう build.gradle に設定を追加します。

bootRun {
    jvmArgs = jvmArgsForTask +
            [
                    "-Dspring.profiles.active=develop",
                    "-XX:TieredStopAtLevel=1"
            ]
}

clean {
    doLast {
        rootProject.file("out").deleteDir()
        rootProject.file("src/main/generated").deleteDir()
        rootProject.file("src/test/generated_tests").deleteDir()
    }
}

再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行してみましたが、test タスクで大量にテストが失敗する状況が変わりません。

f:id:ksby:20211012160925p:plain

src/test/resources/logback.xml を削除しましたが、関係ないようなので元に戻します。

Web でいろいろ検索してみるとなぜか珍しく自分の過去の記事の Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その2 )( Spring Boot を 2.2.2 → 2.2.9 へ、Gradle を 6.0.1 → 6.5.1 へバージョンアップする ) がヒットしました。この時は org.xml.sax.SAXNotSupportedException: not supported setting property http://xml.org/sax/properties/lexical-handler というエラーでしたが、SpotBugs の依存関係から pull-parser を削除して解決しています。

今回は Parser configuration error occurred org.xml.sax.SAXNotRecognizedException: unrecognized feature http://xml.org/sax/features/external-general-entities というエラーが出て失敗していますが、同じ原因のような気がするので SpotBugs の依存関係から pull-parser を削除してみます。

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

dependencies {
    ..........

    // for SpotBugs
    compileOnly("com.github.spotbugs:spotbugs:${spotbugsVersion}") {
        exclude group: "pull-parser", module: "pull-parser"
    }
    ..........
  • exclude group: "pull-parser", module: "pull-parser" を追加します。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20211012170605p:plain

2.5.4 までは問題なかったのに 2.5.5 でエラーになったのかは謎です。。。

Eclipse Adoptium OpenJDK(Eclipse Temurin) を 11.0.12+7 → 17+35 へバージョンアップする。。。のは一旦諦める

Eclipse Adoptium OpenJDK(Eclipse Temurin)の 17+35 は Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その13 )( Spring Boot を 2.5.4 → 2.5.5 へ、Eclipse Adoptium OpenJDK(Eclipse Temurin) を 11.0.12+7 → 17+35 へバージョンアップする ) でインストール済なので、プロジェクトで使用する JDK の設定を変更します。

IntelliJ IDEA のメインメニューから「File」-「Project Structure...」を選択し、「Project Structure」ダイアログが表示されたら「Project SDK」で「17+35」を選択して「OK」ボタンをクリックします。

f:id:ksby:20211012172055p:plain

メイン画面に戻ると画面右下に「Indexing...」の表示が出るので、終了するまで待ちます。

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

sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
  • JavaVersion.VERSION_11JavaVersion.VERSION_17 に変更します。

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

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると compileJava タスクが error-prone が原因でエラーになるので、一旦 build.gradle の error-prone の設定を全てコメントアウトします(後でバージョンアップして解消する予定)。

f:id:ksby:20211012173026p:plain

再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行しますが、今度は spotBugsMain タスクが大量にログを出力し、configureChromeDriverBinary タスクでエラーになりました。

f:id:ksby:20211012173811p:plain

SpotBugs や error-prone をバージョンアップしてから JDK 17 にバージョンアップした方が良さそうな気がしたので、今回は JDK 11 に切り戻すことにします。

切り戻してから clean タスク実行 → Rebuild Project 実行 → build タスクを実行して "BUILD SUCCESSFUL" のメッセージが出力されることを確認しておきます。

f:id:ksby:20211012175311p:plain

Spring Boot のバージョンアップや JDK 17 へのバージョンアップは難しくないイメージがあったのですが、今回は結構辛いです。。。 バージョンアップはこまめにやった方がいいな、というのが正直な感想です。

履歴

2021/10/12
初版発行。

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 + npm + Geb で入力フォームを作ってテストする ( その99 )( Gradle を 6.9.1 → 7.2 へ、Spring Boot を 2.4.10 → 2.5.4 へ、Geb を 4.1 → 5.0 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 前回からの続きです。

参照したサイト・書籍

  1. Difference between mockito-core vs mockito-inline
    https://stackoverflow.com/questions/65986197/difference-between-mockito-core-vs-mockito-inline

  2. Mocking static methods (since 3.4.0)
    https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#static_mocks

  3. mvc controller test with session attribute
    https://stackoverflow.com/questions/26341400/mvc-controller-test-with-session-attribute

目次

  1. JUnit 4 の依存関係が残っているので削除する
  2. gebTest タスクが成功するか確認する
  3. powermock を利用しているテストを powermock なしで動作するよう変更する
  4. mockito-inline を依存関係に追加した後にテストが失敗する原因を調査する
  5. apply(sharedHttpSession()) を呼び出して MockMvc の request 間で session 情報が自動で共有されるようにする
  6. @Unroll アノテーションを削除する

手順

JUnit 4 の依存関係が残っているので削除する

gradlew dependencies コマンドを実行して、出力結果から JUnit 4(junit:junit:4) を検索すると以下の2つのモジュールでヒットしました。

  • org.springframework.boot:spring-boot-starter-web
  • com.icegreen:greenmail
+--- org.springframework.boot:spring-boot-starter-web -> 2.5.4
|    ..........
|    +--- org.springframework.boot:spring-boot-starter-json:2.5.4
|    |    +--- org.springframework.boot:spring-boot-starter:2.5.4 (*)
|    |    +--- org.springframework:spring-web:5.3.9
|    |    |    +--- org.springframework:spring-beans:5.3.9 (*)
|    |    |    \--- org.springframework:spring-core:5.3.9 (*)
|    |    +--- com.fasterxml.jackson.core:jackson-databind:2.12.4
|    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.12.4
|    |    |    |    \--- com.fasterxml.jackson:jackson-bom:2.12.4
|    |    |    |         +--- junit:junit:4.13.1 -> 4.13.2 (c)
|    |    |    |         +--- com.fasterxml.jackson.core:jackson-annotations:2.12.4 (c)
|    |    |    |         +--- com.fasterxml.jackson.core:jackson-core:2.12.4 (c)
|    |    |    |         +--- com.fasterxml.jackson.core:jackson-databind:2.12.4 (c)
|    |    |    |         +--- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.12.4 (c)
|    |    |    |         +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.12.4 (c)
|    |    |    |         \--- com.fasterxml.jackson.module:jackson-module-parameter-names:2.12.4 (c)
|    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.12.4
|    |    |    |    \--- com.fasterxml.jackson:jackson-bom:2.12.4 (*)
|    |    |    \--- com.fasterxml.jackson:jackson-bom:2.12.4 (*)
|    |    +--- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.12.4
|    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.12.4 (*)
|    |    |    +--- com.fasterxml.jackson.core:jackson-databind:2.12.4 (*)
|    |    |    \--- com.fasterxml.jackson:jackson-bom:2.12.4 (*)
|    |    +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.12.4
|    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.12.4 (*)
|    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.12.4 (*)
|    |    |    +--- com.fasterxml.jackson.core:jackson-databind:2.12.4 (*)
|    |    |    \--- com.fasterxml.jackson:jackson-bom:2.12.4 (*)
|    |    \--- com.fasterxml.jackson.module:jackson-module-parameter-names:2.12.4
|    |         +--- com.fasterxml.jackson.core:jackson-core:2.12.4 (*)
|    |         +--- com.fasterxml.jackson.core:jackson-databind:2.12.4 (*)
|    |         \--- com.fasterxml.jackson:jackson-bom:2.12.4 (*)
|    ..........
..........
+--- com.icegreen:greenmail:1.6.5
|    +--- com.sun.mail:jakarta.mail:1.6.7 (*)
|    +--- org.slf4j:slf4j-api:1.7.32
|    \--- junit:junit:4.13.2

build.gradle を変更します。

dependencies {
    ..........

    // dependency-management-plugin によりバージョン番号が自動で設定されるもの
    // Appendix F. Dependency versions ( https://docs.spring.io/spring-boot/docs/2.1.4.RELEASE/reference/html/appendix-dependency-versions.html ) 参照
    implementation("org.springframework.boot:spring-boot-starter-web") {
        exclude group: "junit", module: "junit"
    }
    ..........

    // dependency-management-plugin によりバージョン番号が自動で設定されないもの、あるいは最新バージョンを指定したいもの
    ..........
    testImplementation("com.icegreen:greenmail:1.6.5") {
        exclude group: "junit", module: "junit"
    }
  • implementation("org.springframework.boot:spring-boot-starter-web")testImplementation("com.icegreen:greenmail:1.6.5")exclude group: "junit", module: "junit" を追加します。

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

再度 gradlew dependencies コマンドを実行して JUnit 4 が依存関係から削除されていることを確認します。

clean タスク実行 → Rebuild Project を実行すると、ksbysample/webapp/bootnpmgeb/web/inquiry/form/InquiryInput02FormValidatorTest.groovy でエラーが発生しました。

f:id:ksby:20211010230408p:plain

エラーメッセージの箇所にジャンプすると @RunWith(Enclosed) が使用されていました。テストが認識されていないのはこのファイルでした。

f:id:ksby:20211010230605p:plain

以下の点を変更します。

  • @RunWith(Enclosed) を削除します。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されて、成功したテストの件数が 147 → 146 になりました。powermock を利用したテストを 1件コメントアウトしているので、これで全てのテストが認識されたことになります。

f:id:ksby:20211010231529p:plain

gebTest タスクが成功するか確認する

まず src/test/groovy/geb/gebspec/inquiry/InquiryTestSpec.groovy で MailServerResource が使用されていたので MailServerExtension に変更します。

class InquiryTestSpec extends GebSpec {

    MailServerExtension mailServerExtension = new MailServerExtension()

    Sql sql

    def setup() {
        mailServerExtension.start()

        // 外部プロセスから接続するので H2 TCP サーバへ接続する
        sql = Sql.newInstance("jdbc:h2:tcp://localhost:9092/mem:bootnpmgebdb", "sa", "")
        sql.execute("truncate table INQUIRY_DATA")
    }

    def cleanup() {
        mailServerExtension.stop()
        sql.close()
    }
  • InquiryTestSpec クラスでは @SringBootTest アノテーションを付与していないため @Autowired を付与しても意味がないので、@Rule アノテーションを削除し MailServerResource mailServerResource = new MailServerResource()MailServerExtension mailServerExtension = new MailServerExtension() に変更します。
  • setup メソッド内に mailServerExtension.start() を追加します。
  • cleanup メソッド内に mailServerExtension.stop() を追加します。
  • テストクラス内の mailServerResource.mailServerExtension. に変更します。

gebTest タスクを実行すると、テストが 1件も実行されていません。。。

f:id:ksby:20211010233832p:plain

Geb のテストクラスに @Test アノテーションは付与していないしテストが認識されない原因は何だろう?と思いつつ調査した結果、build.gradle に記述されている chromeTest、filrefoxTest タスクに useJUnitPlatform() が記述されていないためでした。

build.gradle の task "${driver}Test"(type: Test) { ... } 内に useJUnitPlatform() を追加します。

def drivers = ["chrome", "firefox"]
drivers.each { driver ->
    task "${driver}Test"(type: Test) {
        // 前回実行時以降に何も更新されていなくても必ず実行する
        outputs.upToDateWhen { false }
        systemProperty "geb.env", driver
        exclude "ksbysample/**"

        // for JUnit 5
        useJUnitPlatform()

        testLogging {
            afterSuite printTestCount
        }
    }
}
task gebTest {
    dependsOn drivers.collect { tasks["${it}Test"] }
    enabled = false
}

gebTest タスクを実行すると全てのテストが実行されて成功しました。

f:id:ksby:20211010235424p:plain

powermock を利用しているテストを powermock なしで動作するよう変更する

src/test/groovy/ksbysample/webapp/bootnpmgeb/web/inquiry/form/InquiryInput02FormValidatorTest.groovy に記述している powermock を利用しているテストを、

    @RunWith(PowerMockRunner)
    @PowerMockRunnerDelegate(SpringRunner)
    @SpringBootTest
    @PrepareForTest(EmailValidator)
    @PowerMockIgnore(["javax.management.*", "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.dom.*", "com.sun.org.apache.xalan.*"])
    static class InquiryInput02FormValidator_メールアドレス {

        @Autowired
        private InquiryInput02FormValidator input02FormValidator

        Errors errors
        InquiryInput02Form inquiryInput02Form

        @Before
        void setup() {
            errors = TestHelper.createErrors()
            inquiryInput02Form = new InquiryInput02Form(
                    zipcode1: "102"
                    , zipcode2: "0072"
                    , address: "東京都千代田区飯田橋1-1"
                    , tel1: ""
                    , tel2: ""
                    , tel3: ""
                    , email: "taro.tanaka@sample.co.jp")
        }

        @Test
        void "メールアドレスの Validation のテスト"() {
            when: "EmailValidator.validate が true を返すように設定してテストする"
            PowerMockito.mockStatic(EmailValidator)
            PowerMockito.when(EmailValidator.validate(Mockito.any())) thenReturn(true)
            input02FormValidator.validate(inquiryInput02Form, errors)

            then: "入力チェックエラーは発生しない"
            assert errors.hasErrors() == false
            assert errors.getAllErrors().size() == 0
            // EmailValidator.validate が呼び出されていることをチェックする
            PowerMockito.verifyStatic(EmailValidator, Mockito.times(1))
            EmailValidator.validate("taro.tanaka@sample.co.jp")

            and: "EmailValidator.validate が false を返すように設定してテストする"
            PowerMockito.when(EmailValidator.validate(Mockito.any())) thenReturn(false)
            input02FormValidator.validate(inquiryInput02Form, errors)

            then: "入力チェックエラーが発生する"
            assert errors.hasErrors() == true
            assert errors.getAllErrors().size() == 1
        }

    }

以下のように変更します。

    @Nested
    @SpringBootTest
    static class InquiryInput02FormValidator_メールアドレス {

        @Autowired
        private InquiryInput02FormValidator input02FormValidator

        Errors errors
        InquiryInput02Form inquiryInput02Form

        @BeforeEach
        void setup() {
            errors = TestHelper.createErrors()
            inquiryInput02Form = new InquiryInput02Form(
                    zipcode1: "102"
                    , zipcode2: "0072"
                    , address: "東京都千代田区飯田橋1-1"
                    , tel1: ""
                    , tel2: ""
                    , tel3: ""
                    , email: "taro.tanaka@sample.co.jp")
        }

        @Test
        void "メールアドレスの Validation のテスト"() {
            when: "EmailValidator.validate が true を返すように設定してテストする"
            Mockito.mockStatic(EmailValidator)
            Mockito.when(EmailValidator.validate(Mockito.any())).thenReturn(true)
            input02FormValidator.validate(inquiryInput02Form, errors)

            then: "入力チェックエラーは発生しない"
            assert errors.hasErrors() == false
            assert errors.getAllErrors().size() == 0
            // EmailValidator.validate が呼び出されていることをチェックする
            Mockito.verify(EmailValidator, Mockito.times(1))
            EmailValidator.validate("taro.tanaka@sample.co.jp")

            and: "EmailValidator.validate が false を返すように設定してテストする"
            Mockito.when(EmailValidator.validate(Mockito.any())) thenReturn(false)
            input02FormValidator.validate(inquiryInput02Form, errors)

            then: "入力チェックエラーが発生する"
            assert errors.hasErrors() == true
            assert errors.getAllErrors().size() == 1
        }

    }

Mockito で static method のテストを実装するには mockito-inline が必要なので、build.gradle の dependencies block に testImplementation("org.mockito:mockito-inline") を追加します。

dependencies {
    ..........
    testImplementation("org.codehaus.groovy:groovy-sql")
    testImplementation("org.mockito:mockito-inline")

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

テスト単体で実行すると成功しました。

f:id:ksby:20211011002454p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、test タスクで今回変更したテスト以外のテストがなぜか失敗しました。。。

f:id:ksby:20211011003133p:plain

mockito-inline を依存関係に追加した後にテストが失敗する原因を調査する

エラーの原因を調べようとテストを IntelliJ IDEA から単体で実行してみると成功します。

f:id:ksby:20211011160108p:plain

mockito-inline を依存関係に追加したのが原因だろうと思い、依存関係から外して powermock を利用しているテストを powermock なしで動作するよう変更する で変更したテストもコメントアウトして build タスクを実行すると、テストは全て成功します。

f:id:ksby:20211011161040p:plain

mockito-inline を依存関係に追加し、コメントアウトしたテストも元に戻します。

コンソールに出力されているエラーメッセージだけでは詳細が分からないので build/reports/tests/test/index.html のレポートファイルを開いてみると、失敗した手テスト全てで Caused by: java.lang.IllegalArgumentException: セットされるはずのデータがセットされていません のログが出力されていました。

f:id:ksby:20211011214003p:plain

上のログから該当箇所を確認してみると、mockito-inline が依存関係に追加されると mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf()).session(session)) でデータを渡せなくなる(TestHelper.postForm メソッドでデータをセットできない?)ように見えるのですが、これだけでは解決の仕方が分かりません。

Web でいろいろ検索して調べたところ、以下の2つのページを見つけました。

Mockito.mockStatic メソッドを使用する場合には try-with-resources 構文を使うように書かれていますね。。。 まさか、Mockito.mockStatic 戻り値を変数に取っておいて close メソッドを呼び出す必要があるとは思いませんでした。

powermock を利用しているテストを powermock なしで動作するよう変更する で変更したテストを以下のように変更します。

        @Test
        void "メールアドレスの Validation のテスト"() {
            given:
            MockedStatic mockedEmailValidator = Mockito.mockStatic(EmailValidator)

            when: "EmailValidator.validate が true を返すように設定してテストする"
            Mockito.when(EmailValidator.validate(Mockito.any())).thenReturn(true)
            input02FormValidator.validate(inquiryInput02Form, errors)

            then: "入力チェックエラーは発生しない"
            assert errors.hasErrors() == false
            assert errors.getAllErrors().size() == 0
            // EmailValidator.validate が呼び出されていることをチェックする
            Mockito.verify(EmailValidator, Mockito.times(1))
            EmailValidator.validate("taro.tanaka@sample.co.jp")

            and: "EmailValidator.validate が false を返すように設定してテストする"
            Mockito.when(EmailValidator.validate(Mockito.any())) thenReturn(false)
            input02FormValidator.validate(inquiryInput02Form, errors)

            then: "入力チェックエラーが発生する"
            assert errors.hasErrors() == true
            assert errors.getAllErrors().size() == 1

            cleanup:
            mockedEmailValidator.close()
        }
  • given block を追加して Mockito.mockStatic を呼び出している行をこの下に移動し、Mockito.mockStatic(EmailValidator)MockedStatic mockedEmailValidator = Mockito.mockStatic(EmailValidator) に変更します。
  • cleanup block を追加し、mockedEmailValidator.close() を追加します。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20211012091902p:plain

apply(sharedHttpSession()) を呼び出して MockMvc の request 間で session 情報が自動で共有されるようにする

mockito-inline を依存関係に追加した後にテストが失敗する原因を調査する の調査をしていた時に mvc controller test with session attribute のページを見つけました。MockMvc のインスタンスを生成する時に apply(sharedHttpSession()) を呼び出せば session 情報が自動で共有されるようになるとのこと。

以下のような実装の場合、

    @BeforeEach
    void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context)
                .apply(springSecurity())
                .build()
    }

    @Test
    void "完了画面で「入力画面へ」ボタンをクリックして入力画面1へ戻ると入力していたデータがクリアされる"() {
        when: "入力画面1で項目全てに入力して「次へ」ボタンをクリックする"
        MvcResult result = mockMvc.perform(TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf()))
                .andExpect(status().isFound())
                .andExpect(redirectedUrlPattern("**/inquiry/input/02"))
                .andReturn()
        MockHttpSession session = result.getRequest().getSession()

        and: "入力画面2で項目全てに入力して「次へ」ボタンをクリックする"
        mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf()).session(session))
                .andExpect(status().isFound())
                .andExpect(redirectedUrlPattern("**/inquiry/input/03"))

        ..........
    }

以下のように変更します。

    @BeforeEach
    void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context)
                .apply(springSecurity())
                .apply(sharedHttpSession())
                .build()
    }

    @Test
    void "完了画面で「入力画面へ」ボタンをクリックして入力画面1へ戻ると入力していたデータがクリアされる"() {
        when: "入力画面1で項目全てに入力して「次へ」ボタンをクリックする"
        mockMvc.perform(TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf()))
                .andExpect(status().isFound())
                .andExpect(redirectedUrlPattern("**/inquiry/input/02"))

        and: "入力画面2で項目全てに入力して「次へ」ボタンをクリックする"
        mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf()))
                .andExpect(status().isFound())
                .andExpect(redirectedUrlPattern("**/inquiry/input/03"))

        ..........
    }
  • MockMvcBuilders クラスで MockMvc のインスタンスを生成している処理に .apply(sharedHttpSession()) を追加します。
  • テストメソッド内で MvcResult result =.andReturn() を削除します。
  • MockHttpSession session = result.getRequest().getSession() も削除します。
  • その下の .session(session) の部分を全て削除します。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20211012095031p:plain

ちなみに @AutoConfigureMockMvc アノテーションを付与して MockMvc のインスタンスを自動生成した場合、session 情報は共有されませんでした。apply(sharedHttpSession()) による session 情報共有の機能を利用したい場合には自分でインスタンスを生成する必要があります。

@Unroll アノテーションを削除する

Spock 2 から @Unroll アノテーションの記述が不要になったので、削除します。

削除後に clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されて、テスト数も削除前と同じ 147 でした。

f:id:ksby:20211012100409p:plain

履歴

2021/10/12
初版発行。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その99 )( Gradle を 6.9.1 → 7.2 へ、Spring Boot を 2.4.10 → 2.5.4 へ、Geb を 4.1 → 5.0 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その98 )( Gradle を 6.4 → 6.9.1 へ、Spring Boot を 2.2.7 → 2.4.10 へ、Geb を 3.4 → 4.1 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Gradle を 6.9.1 → 7.2 へバージョンアップします。
    • Spring Boot を 2.4.10 → 2.5.4 へ、Geb を 4.1 → 5.0 へバージョンアップします。
    • 今回だけでは完了しなかったので、2回に分けます。

参照したサイト・書籍

  1. erdi / webdriver-binaries-gradle-plugin
    https://github.com/erdi/webdriver-binaries-gradle-plugin

目次

  1. Gradle を 6.9.1 → 7.2 へバージョンアップする
  2. Spring Boot を 2.4.10 → 2.5.4 へ、Geb を 4.1 → 5.0 へバージョンアップする。。。がエラーが出てバージョンアップできず
  3. configureChromeDriverBinary タスクでエラーになる原因を調査した結果、Gradle Plugin を com.energizedwork.webdriver-binaries → com.github.erdi.webdriver-binaries に切り替える
  4. test タスクで実行されるテストから src/test/groovy/geb/ の下のテストを除外する
  5. org.junit.Test アノテーションが付いているテストを org.junit.jupiter.api.Test アノテーションに変更する
  6. 続く。。。

手順

Gradle を 6.9.1 → 7.2 へバージョンアップする

build.gradle の wrapper タスクの記述を以下のように変更します。

wrapper {
    gradleVersion = "7.2"
    distributionType = Wrapper.DistributionType.ALL
}
  • gradleVersion = "6.9.1"gradleVersion = "7.2" に変更します。

コマンドプロンプトから gradlew wrapper --gradle-version=7.2gradlew --version コマンドを実行します。gradlew --stop で Gradle Deamon を止めただけでは java.lang.IllegalArgumentException: Unsupported class file major version 61 のエラーメッセージが出たので、PC を再起動してからコマンドを実行しています。

f:id:ksby:20211010092309p:plain

gradle/wrapper/gradle-wrapper.properties は以下の内容になります。

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その4 )( Gradle を 6.9.1 → 7.2 へバージョンアップする ) で実施した変更内容を build.gradle に反映します。

tasks.named("compileTestJava").configure {
    options.errorprone.enabled = false
}
bootJar {
    duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
jar {
    enabled = false
}

// for Doma 2
// Copy the resources referred by the Doma annotation processors to
// the destinationDir of the compileJava task
task copyDomaResources(type: Sync) {
    from sourceSets.main.resources.srcDirs
    into compileJava.destinationDirectory
    include "doma.compile.config"
    include "META-INF/**/*.sql"
    include "META-INF/**/*.script"
}
compileJava.dependsOn copyDomaResources
  • bootJar { duplicatesStrategy = DuplicatesStrategy.INCLUDE } を追加します。
  • jar { enabled = false } を追加します。
  • copyDomaResources タスクの以下の点を変更します。
    • into compileJava.destinationDirinto compileJava.destinationDirectory

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。。。が、Could not find method testCompile() のエラーメッセージが表示されました。

f:id:ksby:20211010093406p:plain

古い文法のままでした。。。 その下の testRuntime も testRuntimeOnly に変更されているので、build.gradle を以下のように変更します。

dependencies {
    ..........

    // for JUnit 5
    // junit-jupiter で junit-jupiter-api, junit-jupiter-params, junit-jupiter-engine の3つが依存関係に追加される
    testImplementation("org.junit.jupiter:junit-jupiter")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
  • testCompile("org.junit.jupiter:junit-jupiter")testImplementation("org.junit.jupiter:junit-jupiter") に変更します。
  • testRuntime("org.junit.platform:junit-platform-launcher")testRuntimeOnly("org.junit.platform:junit-platform-launcher") に変更します。

再度 Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新すると、今度は問題なく終了しました。

Spring Boot を 2.4.10 → 2.5.4 へ、Geb を 4.1 → 5.0 へバージョンアップする。。。がエラーが出てバージョンアップできず

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

buildscript {
    ext {
        group "ksbysample"
        version "2.5.4"
    }
    repositories {
        mavenCentral()
        gradlePluginPortal()
    }
    dependencies {
        // for doma-codegen-plugin
        classpath "com.h2database:h2:1.4.200"
    }
}

plugins {
    id "java"
    id "groovy"
    id "eclipse"
    id "idea"
    id "org.springframework.boot" version "2.5.4"
    id "io.spring.dependency-management" version "1.0.11.RELEASE"
    id "net.ltgt.errorprone" version "1.1.1"
    id "checkstyle"
    id "com.github.spotbugs" version "4.0.8"
    id "pmd"
    id "com.github.node-gradle.node" version "3.1.1"
    id "com.gorylenko.gradle-git-properties" version "2.3.1"
    id "com.energizedwork.webdriver-binaries" version "1.4"
    id "org.seasar.doma.codegen" version "1.4.1"
}

..........

dependencyManagement {
    imports {
        // mavenBom は以下の URL のものを使用する
        // https://repo.spring.io/release/org/springframework/boot/spring-boot-starter-parent/2.1.4.RELEASE/
        // bomProperty に指定可能な property は以下の URL の BOM に記述がある
        // https://repo.spring.io/release/org/springframework/boot/spring-boot-dependencies/2.1.4.RELEASE/spring-boot-dependencies-2.1.4.RELEASE.pom
        mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
        mavenBom("org.junit:junit-bom:5.8.1")
    }
}

dependencies {
    def spockVersion = "2.0-groovy-3.0"
    def lombokVersion = "1.18.20"
    def domaVersion = "2.49.0"
    def errorproneVersion = "2.3.4"
    def seleniumVersion = "3.141.59"
    def spotbugsVersion = "4.0.2"

    // dependency-management-plugin によりバージョン番号が自動で設定されるもの
    // Appendix F. Dependency versions ( https://docs.spring.io/spring-boot/docs/2.1.4.RELEASE/reference/html/appendix-dependency-versions.html ) 参照
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-validation")
    implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-freemarker")
    implementation("org.springframework.boot:spring-boot-starter-mail")
    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    runtimeOnly("org.springframework.boot:spring-boot-devtools")
    implementation("org.springframework.session:spring-session-core")
    implementation("org.springframework.session:spring-session-jdbc")
    implementation("org.codehaus.janino:janino")
    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude group: "org.junit.vintage", module: "junit-vintage-engine"
    }
    testImplementation("org.springframework.security:spring-security-test")
    testImplementation("org.yaml:snakeyaml")
    testImplementation("org.codehaus.groovy:groovy-sql")

    // dependency-management-plugin によりバージョン番号が自動で設定されないもの、あるいは最新バージョンを指定したいもの
    implementation("com.integralblue:log4jdbc-spring-boot-starter:2.0.0")
    implementation("org.flywaydb:flyway-core:7.14.1")
    implementation("com.h2database:h2:1.4.200")
    implementation("com.github.rozidan:modelmapper-spring-boot-starter:2.3.1")
    implementation("com.google.guava:guava:31.0.1-jre")
    implementation("org.apache.commons:commons-lang3:3.12.0")
    testImplementation("org.dbunit:dbunit:2.7.2")
    testImplementation("org.assertj:assertj-core:3.21.0")
    testImplementation("org.spockframework:spock-core:${spockVersion}")
    testImplementation("org.spockframework:spock-spring:${spockVersion}")
    testImplementation("org.jsoup:jsoup:1.14.3")
    testImplementation("com.icegreen:greenmail:1.6.5")

    // for lombok
    annotationProcessor("org.projectlombok:lombok:${lombokVersion}")
    compileOnly("org.projectlombok:lombok:${lombokVersion}")

    // for Doma
    implementation("org.seasar.doma:doma-core:${domaVersion}")
    annotationProcessor("org.seasar.doma:doma-processor:${domaVersion}")

    // for Error Prone ( http://errorprone.info/ )
    errorprone("com.google.errorprone:error_prone_core:${errorproneVersion}")
    compileOnly("com.google.errorprone:error_prone_annotations:${errorproneVersion}")

    // PowerMock
    testImplementation("org.powermock:powermock-module-junit4:${powermockVersion}")
    testImplementation("org.powermock:powermock-api-mockito2:${powermockVersion}")

    // for Geb + Spock
    testImplementation("org.gebish:geb-spock:5.0")
    testImplementation("org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}")
    testImplementation("org.seleniumhq.selenium:selenium-firefox-driver:${seleniumVersion}")
    testImplementation("org.seleniumhq.selenium:selenium-support:${seleniumVersion}")

    // for SpotBugs
    compileOnly("com.github.spotbugs:spotbugs:${spotbugsVersion}")
    compileOnly("net.jcip:jcip-annotations:1.0")
    compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}")
    testImplementation("com.google.code.findbugs:jsr305:3.0.2")
    spotbugsStylesheets("com.github.spotbugs:spotbugs:${spotbugsVersion}")
    spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.10.1")

    // for JUnit 5
    // junit-jupiter で junit-jupiter-api, junit-jupiter-params, junit-jupiter-engine の3つが依存関係に追加される
    testImplementation("org.junit.jupiter:junit-jupiter")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

..........

bootRun {
    jvmArgs = jvmArgsForTask +
            [
                    "-Dspring.profiles.active=develop",
                    "-XX:TieredStopAtLevel=1"
            ]
}

tasks.withType(Test) {
    jvmArgs = jvmArgsForTask +
            ["-Dspring.profiles.active=unittest"]
}
test {
    // test タスクの jvmArgs は tasks.withType(Test) { ... } で定義している

    // for JUnit 5
    useJUnitPlatform()

    testLogging {
        afterSuite printTestCount
    }
}

..........

Spring Boot 2.5.4 へのバージョンアップとして以下の点を変更します。

  • buildscript block の以下の点を変更します。
    • version "2.4.10"version "2.5.4"
  • plugins block の以下の点を変更します。
    • id "org.springframework.boot" version "2.4.10"id "org.springframework.boot" version "2.5.4"
  • dependencyManagement block の以下の点を変更します。
    • mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES) { bomProperty "groovy.version", "2.5.15" }mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)

各種ライブラリのバージョンアップとして以下の点を変更します。

  • dependencyManagement block の以下の点を変更します。
    • mavenBom("org.junit:junit-bom:5.7.2")mavenBom("org.junit:junit-bom:5.8.1")
  • dependencies block の以下の点を変更します。
    • def spockVersion = "1.3-groovy-2.5"def spockVersion = "2.0-groovy-3.0"
    • testImplementation("org.codehaus.groovy:groovy-sql") を追加します。
    • testImplementation("org.gebish:geb-spock:4.1") { exclude group: "org.codehaus.groovy", module: "groovy-all" }testImplementation("org.gebish:geb-spock:5.0")
    • https://gebish.org/manual/current/#installation-usage を見ると selenium-apiselenium-remote-driver の2つは必要ないようなので、以下の2行を削除します。
      • testImplementation("org.seleniumhq.selenium:selenium-api:${seleniumVersion}")
      • testImplementation("org.seleniumhq.selenium:selenium-remote-driver:${seleniumVersion}")
    • powermock を依存関係から削除するため、以下の3行を削除します。
      • def powermockVersion = "2.0.7"
      • testImplementation("org.powermock:powermock-module-junit4:${powermockVersion}")
      • testImplementation("org.powermock:powermock-api-mockito2:${powermockVersion}")
  • def jvmArgsAddOpens = [ ... ] を削除します。
  • テストが全て JUnit 5 ベースになるので、testJUnit4AndSpock タスクを削除します。
    • task testJUnit4AndSpock(type: Test) { ... }
    • test.dependsOn testJUnit4AndSpock

ksbysample/webapp/bootnpmgeb/web/inquiry/form/InquiryInput02FormValidatorTest.groovy に powermock を利用したテストが記述されていますが、このままでは build が通らないので対象のテストをコメントアウトします(後で実装し直します)。

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

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、configureChromeDriverBinary タスクでエラーになりました。。。

f:id:ksby:20211010184036p:plain

configureChromeDriverBinary タスクでエラーになる原因を調査した結果、Gradle Plugin を com.energizedwork.webdriver-binaries → com.github.erdi.webdriver-binaries に切り替える

gradlew configureChromeDriverBinary --stacktrace コマンドを実行してみると Caused by: java.lang.NoSuchMethodError: 'void org.gradle.wrapper.PathAssembler.<init>(java.io.File)' のエラーメッセージが出力されましたが、これでは原因がよく分かりません。

f:id:ksby:20211010184417p:plain

com.energizedwork.webdriver-binariesGoogle で検索したところ、erdi / webdriver-binaries-gradle-plugin のページにたどり着きました。新しい Gradle Plugin が出ているようなので、こちらに切り替えます。

plugins {
    ..........
    id "com.github.erdi.webdriver-binaries" version "2.6"
    ..........
}

..........

webdriverBinaries {
    chromedriver {
        version = "94.0.4606.41"
        architecture = "X86"
        fallbackTo32Bit = true
    }
    geckodriver {
        version = "0.29.1"
        architecture = "X86_64"
    }
}

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

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、configureChromeDriverBinary タスクは正常終了しましたが test タスクでエラーが発生しました。

f:id:ksby:20211010190535p:plain

test タスクで実行されるテストから src/test/groovy/geb/ の下のテストを除外する

エラーになったテスト 13個は全て src/test/groovy/geb/gebspec/inquiry/InquiryTestSpec.groovy のテストでした。Spock、Geb がバージョンアップされたことに伴い JUnit 5 ベースのテストに変わったので、test タスクの実行対象になったことが原因です。Geb のテストを test タスクで実行する必要はないので除外します。

build.gradle の test タスクに exclude "geb/**" を追加します。

test {
    // test タスクの jvmArgs は tasks.withType(Test) { ... } で定義している

    // Geb のテストを test タスクで実行されないようにする
    exclude "geb/**"

    // for JUnit 5
    useJUnitPlatform()

    testLogging {
        afterSuite printTestCount
    }
}

また src/test/groovy/geb/gebspec/inquiry/InquiryTestSpec.groovy を見て気づいたのですが、JUnit 4 のクラスである org.junit.Rule の色がグレーになっていませんでした。build.gradle に記述されているモジュールの依存関係にまだ JUnit 4 が残っているようなので、後で JUnit 4 を依存関係から取り除くようにします。

f:id:ksby:20211010191414p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されましたが、成功したテストの件数が 147 → 116 と大きく減っていました。おそらく org.junit.Test アノテーションが付いているテストがあって、JUnit 5 から認識されないことが原因でしょう。

f:id:ksby:20211010192113p:plain

org.junit.Test アノテーションが付いているテストを org.junit.jupiter.api.Test アノテーションに変更する

org.junit.Test で検索すると以下の2つのファイルがヒットしました。というより Spock ベースで作成していないテストが全て JUnit 4 ベースで実装されていました。。。

  • src/test/groovy/ksbysample/webapp/bootnpmgeb/web/inquiry/InquiryCompleteControllerTest.groovy
  • src/test/groovy/ksbysample/webapp/bootnpmgeb/web/inquiry/InquiryInputControllerTest.groovy

まず GreenMail の起動・停止に使用している src/test/java/ksbysample/common/test/rule/mail/MailServerResource.javaJUnit 4 の org.junit.rules.ExternalResource を継承して作成されているので、JUnit 5 でも動作するよう変更します。

src/test/java/ksbysample/common/test の下に extension.mail パッケージを作成した後、MailServerExtension.java を新規作成して以下の内容を記述します。最初 BeforeEachCallback, AfterEachCallback インターフェースを実装して自動で起動・停止させようと思ったのですが、Spock では @RegisterExtension を付与しても自動起動・停止しなかったので止めました。

package ksbysample.common.test.extension.mail;

import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.ServerSetup;
import org.springframework.stereotype.Component;

import javax.mail.internet.MimeMessage;
import java.util.Arrays;
import java.util.List;

@Component
public class MailServerExtension {

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

    public void start() {
        greenMail.start();
    }

    public void stop() {
        greenMail.stop();
    }

    public int getMessagesCount() {
        return greenMail.getReceivedMessages().length;
    }

    public List<MimeMessage> getMessages() {
        return Arrays.asList(greenMail.getReceivedMessages());
    }

    public MimeMessage getFirstMessage() {
        MimeMessage message = null;
        MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
        if (receivedMessages.length > 0) {
            message = receivedMessages[0];
        }
        return message;
    }

}

src/test/java/ksbysample/common/test/rule/mail/MailServerResource.java は削除します。

次に JUnit 4 ベースで作成されている2つのファイルを以下の内容で変更します。

  • import org.junit.Testimport org.junit.jupiter.api.Test に変更します。
  • @RunWith(Enclosed) を削除します。
  • @RunWith(SpringRunner) を削除します。
  • クラスの中にテストクラスを記述して階層構造にしている場合には、中のクラスに @Nested アノテーションを付与します。
  • MailServerResource を MailServerExtension を使用するよう変更します。GreenMail のメールサーバの起動・停止は @BeforeEach@AfterEach アノテーションが付与されたメソッド内で行います。
    @Rule
    public MailServerResource mailServerResource = new MailServerResource()

   ↓  

    @Autowired
    private MailServerExtension mailServerExtension

    @BeforeEach
    void setup() {
        mailServerExtension.start()
        ..........
    }

    @AfterEach
    void cleanup() {
        mailServerExtension.stop()
    }
  • @Before@BeforeEach に変更します。

Spock ベースで実装している src/test/groovy/ksbysample/webapp/bootnpmgeb/web/inquiry/InquiryConfirmControllerTest.groovy も MailServerResource を使用していたので、以下の点を変更します。

  • @RunWith(Enclosed) を削除します。
  • MailServerResource を MailServerExtension を使用するよう変更します。GreenMail のメールサーバの起動・停止は setup メソッド、cleanup メソッド内で行います。
        @Rule
        MailServerResource mailServerResource = new MailServerResource()

   ↓  

        @Autowired
        private MailServerExtension mailServerExtension

        def setup() {
            mailServerExtension.start()
            ..........
        }

        def cleanup() {
            mailServerExtension.stop()
            ..........
        }
  • テストメソッド内の mailServerResource.mailServerExtension. に変更します。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されましたが、成功したテストの件数が 147 → 131 になりました。まだテストメソッドが認識されないものが残っているようです。

f:id:ksby:20211010205913p:plain

続く。。。

長くなったので、次回へ続きます。以下の内容を行う予定です。

  • JUnit 4 の依存関係が残っているので削除する。
  • テスト件数が減っている原因を調査・解消する。
  • gebTest タスクが成功するか確認する。成功しない場合には、その原因を調査・解消する。
  • powermock で実装されたテストを powermock なしで動作するよう変更する。

履歴

2021/10/10
初版発行。