5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

λ... < ユニットテストのテストコード上で Retrolambda が使えない

Last updated at Posted at 2014-12-05

現象

Android でも λ を使える gradle-retrolambda をいれ、順調に無名クラスの冗長な構文を駆逐していきました。
現在ユニットテストは Android Unit Test を利用しているのですが、テストコードの一部を λ に変更して実行してみると以下の様なエラーが出てしまいました()

JAVA_HOMEに JDK 1.7 を設定している場合

Test.java:61: error: illegal start of expression
  .filter(state -> state != State.UNINITIALIZED)

JAVA_HOMEに JDK 1.8 を設定している場合

An exception has occurred in the compiler (1.8.0_25). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
com.sun.tools.javac.code.Symbol$CompletionFailure: class file for java.lang.invoke.MethodType not found

原因

./gradlew test --debug で原因を探ってみるとコンパイル時に-source -tragetオプションが指定されていないことがわかりました。

23:14:30.815 [DEBUG] [org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler] Compiler arguments: -d /app/build/test-classes/debug -g -encoding UTF-8 -bootclasspath /Applications/android-sdk/platforms/android-21/android.jar -classpath 
...

どうやら、Retrolambda はcompileTestDebugJavaタスク時には JDK を 1.8 に差し替えてくれないようです。

解決方法

そこで、自ら Gradle 上で差し替える必要があります。
gradle-retrolambda の ソースコード を参考に doFirst で JDK やパスを差し替えます。

build.gradle
tasks.withType(Test) {
    project.tasks
            .findAll { task -> (task.name ==~ /compileTest.*Java/) }
            .each { task ->
        task.doFirst {
            def buildPath = "$project.buildDir/retrolambda"
            def jarPath = "$buildPath/$project.android.compileSdkVersion"
            def javac = "${project.retrolambda.tryGetJdk()}/bin/javac"

            sourceCompatibility = JavaVersion.VERSION_1_8
            targetCompatibility = JavaVersion.VERSION_1_8

            options.fork = true
            options.compilerArgs += ["-bootclasspath", "$jarPath/android.jar"]
            options.forkOptions.executable = javac
        }
    }
}

JAVA_HOMEに JDK 1.7 を設定している場合、テスト実行は行えるようになるのですが、以下の様なテスト結果が表示されてしまいます。

Test > initializationError FAILED
    java.lang.UnsupportedClassVersionError

この場合、Gradle とクラスで Java のバージョンが違うためJAVA_HOMEに JDK 1.8 を設定してください。

以上でユニットテスト上でも λ が使えるようになります。

やったね!

5
5
0

Register as a new user and use Qiita more conveniently

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?