JUnit5とJacocoレポートとJMockitの共存のさせ方を教えて下さい。
受付中
回答 0
投稿
- 評価
- クリップ 1
- VIEW 2,071
前提・実現したいこと
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%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる