質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.09%

JUnit5とJacocoレポートとJMockitの共存のさせ方を教えて下さい。

受付中

回答 0

投稿

  • 評価
  • クリップ 1
  • VIEW 2,071

score 6

前提・実現したいこと

JUnit5とJacocoレポートとJMockitの共存のさせ方を教えて下さい。
JMockitを使ってクラスメソッドをMock化したテストコードを実行させたいのですが、
Gradle上だとエラーが発生してしまいます。
Eclipse上で動作させると上手く動作するのですが、Gradleコマンドを実行すると駄目です。
どなたかご教示頂けないでしょうか。

前提
SpringBoot2.1.6で開発しています。
JUnit4+PowerMockitを使ったレガシーコードが混在しており、カバレッジ反映の為に
Jacocoレポートの出力設定をbuild.gradleに記述しています。
将来的にはJUnit4とPowerMockitのレガシーコードを駆逐してJUnit5のテストコードに置き換えたいのですが、何処に不備があるのか分からず難儀しております。

発生している問題・エラーメッセージ

jp.co.abc.efg.rest.controller.aa.TargetRestControllerTest > test002() FAILED
    org.opentest4j.AssertionFailedError at TargetRestControllerTest.java:149
        Caused by: java.lang.ArrayIndexOutOfBoundsException at TargetRestControllerTest.java:108

該当のソースコード

// テストクラス
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import jp.co.abc.efg.MainApiApplication;
import jp.co.abc.efg.core.bean.CommonUserInfo;
import jp.co.abc.efg.core.common.CommonUtils;
import jp.co.abc.efg.core.config.MyBatisConfiguration;
import mockit.Mock;
import mockit.MockUp;
import mockit.integration.junit5.JMockitExtension;

@SpringJUnitWebConfig(classes = {MainApiApplication.class , MyBatisConfiguration.class})
@SpringBootTest
@AutoConfigureMockMvc
@ExtendWith(JMockitExtension.class)
public class TargetRestControllerTest {    
    @Autowired
    private TargetRestController controller;

    @Test
    @Rollback(true)
    public void test002() {
        try { 
            new MockUp<CommonUtils>() {
                @Mock
                public CommonUserInfo getCommonUserInfo() {
                    var userInfo = new CommonUserInfo();
                    userInfo.setUserid("12345678");
                    userInfo.setKnjiempnm("てすと太郎");
                    return userInfo;
                }
            };
            this.controller.refreshHierarchicalMenuInfo();
        } catch (Exception e) {
            Assertions.fail(e);
        }
    }
}

// テスト対象クラス
@RequestMapping(CommonApiEndPoints.BASE_URI)
@RestController
@CrossOrigin
public class TargetRestController {
    @Autowired
    private TargetRestService service;

    @GetMapping(value = CommonApiEndPoints.API_REFRESH_URI, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseJson<AsynchronousProcessingResponseResult> refreshHierarchicalMenuInfo() {
        var responseJson = new ResponseJson<AsynchronousProcessingResponseResult>();
        String taskId = CommonUtils.createUUID();
        this.service.refreshHierarchicalMenuInfo(taskId, OlcScmCommonUtils.getCommonUserInfo());
        var asynchronousProcessingResponseResult = new AsynchronousProcessingResponseResult();
        asynchronousProcessingResponseResult.setPollingId(taskId);
        CommonUtils.setResponseJson(responseJson, responseJson.createDateTime(), asynchronousProcessingResponseResult);
        return responseJson;
    }
}

試したこと

build.gradleのtestタスクにてjvmArgsプロパティにJMockitとJacocoのjarを設定してみましたが、
Error occurred during initialization of VM
Error opening zip file or JAR manifest missing : 
と出る始末。

補足情報(FW/ツールのバージョンなど)

------------------------------------------------------------
Gradle 5.6.4
------------------------------------------------------------

Build time:   2019-11-01 20:42:00 UTC
Revision:     dd870424f9bd8e195d614dc14bb140f43c22da98

Kotlin:       1.3.41
Groovy:       2.5.4
Ant:          Apache Ant(TM) version 1.9.14 compiled on March 12 2019
JVM:          11.0.5 (Oracle Corporation 11.0.5+10-LTS)
OS:           Windows 10 10.0 amd64

// build.gradleは以下の通りです
buildscript {
    ext {
        springBootVersion = '2.1.6.RELEASE'
        springframeworkVersion = '5.1.9.RELEASE'
        junit5Version = '5.5.1'
        jacocoVersion = '0.8.5'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

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

sourceCompatibility = 11
targetCompatibility = 11

repositories {
    mavenCentral()
}

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
    options.compilerArgs = ["-Xlint:deprecation", "-Xlint:unchecked"]
}

jacoco {
    toolVersion = "${jacocoVersion}"
}

configurations {
    jacoco
      jacocoRuntime
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-jdbc:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-cache:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-aop:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-actuator:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-mail:${springBootVersion}")
    compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:latest.integration')
    compile('org.apache.tomcat:tomcat-jdbc:latest.integration')
    compile('org.apache.commons:commons-lang3:latest.integration')
    compile('commons-codec:commons-codec:latest.integration')
    compile('commons-io:commons-io:latest.integration')
    compile('org.hibernate.validator:hibernate-validator:latest.integration')
    compile('org.projectlombok:lombok:latest.integration')
    annotationProcessor('org.projectlombok:lombok:latest.integration')
    compile('javax.cache:cache-api:latest.integration')
    compile('org.ehcache:ehcache:latest.integration')
    compile('io.github.classgraph:classgraph:latest.integration')
    implementation('com.google.code.findbugs:jsr305:latest.integration')
    compile files('lib/ojdbc8.jar')
    compile files('lib/orai18n.jar')
    compile files('lib/orai18n-mapping.jar')
    compile files('lib/ucp.jar')
    testCompile('org.springframework.boot:spring-boot-starter-test') {
        //exclude module: 'junit' // JUnit4 exclude.
        exclude group: "org.mockito", module: "mockito-core"
    }
    testImplementation("org.junit.jupiter:junit-jupiter-api:${junit5Version}") {
        exclude group: "org.junit.platform", module: "junit-platform-commons"
    }
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junit5Version}")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-params:${junit5Version}")
    testRuntimeOnly('org.junit.platform:junit-platform-launcher:latest.integration')
    testRuntimeOnly('org.junit.platform:junit-platform-commons:latest.integration')
    testRuntimeOnly('org.junit.platform:junit-platform-engine:latest.integration')
    testCompile('org.mockito:mockito-core:latest.integration')
    testCompile('org.mockito:mockito-junit-jupiter:latest.integration') {
        exclude group: "org.junit.platform", module: "junit-platform-commons"
    }
    testCompile('org.powermock:powermock-api-mockito2:latest.integration')
    testCompile('org.powermock:powermock-module-junit4:latest.integration')
    testAnnotationProcessor('org.projectlombok:lombok:latest.integration')
    testCompile("org.springframework.boot:spring-boot-starter-mail:${springBootVersion}")
    testCompile('org.jmockit:jmockit:latest.integration')
    testRuntimeOnly("org.jacoco:org.jacoco.ant:${jacocoVersion}:nodeps")
    testRuntimeOnly("org.jacoco:org.jacoco.agent:${jacocoVersion}:runtime")
    testRuntimeOnly('org.junit.vintage:junit-vintage-engine:latest.integration')
}

test {
    dependsOn = ['instrument']
    useJUnitPlatform()
    jvmArgs "-javaagent:${classpath.find { it.name.contains("jmockit") }.absolutePath}"
    finalizedBy = ['jacocoTestReport']
}

task instrument(dependsOn: [classes, project.configurations.jacocoAnt]) {
    inputs.files classes.outputs.files
    File outputDir = new File(project.buildDir, 'instrumentedClasses')
    outputs.dir outputDir
    ext.instrumentedOutputDir = project.buildDir.path + '/instrumentedClasses'
    doFirst {
        project.delete(outputDir)
        ant.taskdef(
                resource: 'org/jacoco/ant/antlib.xml',
                classpath: project.configurations.jacocoAnt.asPath,
                uri: 'jacoco'
        )
        def instrumented = false
        if (file(sourceSets.main.java.outputDir).exists()) {
            def instrumentedClassedDir = "${outputDir}/${sourceSets.main.java}"
            ant.'jacoco:instrument'(destdir: instrumentedClassedDir) {
                fileset(dir: sourceSets.main.java.outputDir, includes: '**/*.class')
            }
            sourceSets.test.runtimeClasspath -= files(sourceSets.main.java.outputDir)
            sourceSets.test.runtimeClasspath += files(instrumentedClassedDir)
            instrumented = true
        }
        if (instrumented) {
            test.jvmArgs += '-noverify'
        }
    }
}

gradle.taskGraph.whenReady { graph ->
    if ( graph.hasTask(instrument) ) {
        tasks.withType( Test ) {
            doFirst {
                systemProperty 'jacoco-agent.destfile', project.buildDir.path + '/jacoco/test.exec'
                classpath = classpath + files(instrument.instrumentedOutputDir) + project.configurations.jacocoRuntime
            }
        }
    }
}

jacocoTestReport {
    dependsOn = ['instrument', 'test']
    additionalSourceDirs = files(sourceSets.main.allJava.srcDirs)
    reports {
        xml.enabled true
        csv.enabled false
        html.enabled true
        sourceSets sourceSets.main
    }
    afterEvaluate {
        classDirectories = files( classDirectories.files.collect {
            fileTree(dir: it, 
                exclude: [
                    'jp/co/abc/efg/core/bean/**',
                    'jp/co/abc/efg/rest/dto/**',
                    'jp/co/abc/efg/rest/mybatis/dto/**'

                ]
            )
        })
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.09%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る