Проблема компиляции тестов Android X + Truth + Guava - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть модуль Gradle библиотеки Android (называемый api) как часть более крупного проекта.Я только что перенес весь проект на AndroidX.У меня теперь есть эта ошибка при запуске инструментария теста на api lib:

 Task :api:checkDebugAndroidTestDuplicateClasses FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':api:checkDebugAndroidTestDuplicateClasses'.
> 1 exception was raised by workers:
  java.lang.RuntimeException: java.lang.RuntimeException: Duplicate class com.google.common.util.concurrent.ListenableFuture found in modules jetified-guava-25.1-android.jar (com.google.guava:guava:25.1-android) and listenablefuture-1.0.jar (com.google.guava:listenablefuture:1.0)

Если я проверяю путь класса времени выполнения для варианта debugAndroidTest:

./gradlew api:dependencies --configuration debugAndroidTestRuntimeClasspath | grep --color -E "guava|$"

я получаюэтот вывод.Я вижу проблему:

------------------------------------------------------------
Project :api
------------------------------------------------------------
debugAndroidTestRuntimeClasspath - Resolved configuration for runtime for variant: debugAndroidTest
+--- project :test_utils
|    +--- project :core
...
|    +--- project :api (*)
|    +--- com.google.android.material:material:1.1.0-alpha03
|    |    +--- androidx.annotation:annotation:1.0.1 -> 1.1.0-alpha01
|    |    +--- androidx.appcompat:appcompat:1.1.0-alpha01
|    |    |    +--- androidx.annotation:annotation:1.0.0 -> 1.1.0-alpha01
|    |    |    +--- androidx.core:core:1.1.0-alpha01 -> 1.1.0-alpha03
|    |    |    |    +--- com.google.guava:listenablefuture:1.0 // <------ GUAVA
|    |    |    |    +--- androidx.annotation:annotation:1.0.1 -> 1.1.0-alpha01
...
+--- com.google.truth:truth:0.42
|    +--- com.google.guava:guava:25.1-android / <------ MORE GUAVA
|    |    +--- com.google.code.findbugs:jsr305:3.0.2
|    |    +--- com.google.errorprone:error_prone_annotations:2.1.3 -> 2.3.1
|    |    +--- com.google.j2objc:j2objc-annotations:1.1
|    |    \--- org.codehaus.mojo:animal-sniffer-annotations:1.14
|    +--- org.checkerframework:checker-compat-qual:2.5.3
|    +--- org.checkerframework:checker-qual:2.5.3
|    +--- junit:junit:4.12 (*)
|    +--- com.googlecode.java-diff-utils:diffutils:1.3.0
|    +--- com.google.auto.value:auto-value-annotations:1.6.2
|    \--- com.google.errorprone:error_prone_annotations:2.3.1
...

Ядро AndroidX зависит от новой сборки guava "ListableFuture-only", а Truth зависит от полной версии Guava 25.

Мне кажется, я понимаюосновная проблема с ListenableFuture: https://groups.google.com/forum/#!topic/guava-announce/Km82fZG68Sw

Какое здесь правильное решение?

Я не хочу полностью исключать Гуаву из Истины (иначе Истина не скомпилируется)

androidTestImplementation("com.google.truth:truth:0.42") {
    exclude group: 'com.google.guava', module: 'guava'
}

Могу ли я исключить + принудительное обновление Guava 27, сделав его зависимостью первого уровня:

androidTestImplementation("com.google.truth:truth:$rootProject.ext.truthVersion") {
    exclude group: 'com.google.guava', module: 'guava'
}
// must add guava as top level dependency to force Truth to use latest version
androidTestImplementation 'com.google.guava:guava:27.0.1-android'

Если я сделаю это, должен ли я использовать версию guava для android или JRE?

Дополнительный вопрос:

Почему я не вижу зависимости от гуавы при просмотре compile classpath?Ошибка является ошибкой времени компиляции, а не ошибкой времени выполнения

./gradlew api:dependencies --configuration debugAndroidTestCompileClasspath | grep --color -E "guava|$"

Результирующие задержки:

debugAndroidTestCompileClasspath - Resolved configuration for compilation for variant: debugAndroidTest
+--- project :test_utils // <----------- why are test_utils deps not listed here???
...
+--- com.google.truth:truth:0.42
|    +--- com.google.guava:guava:25.1-android <------ GUAVA
|    |    +--- com.google.code.findbugs:jsr305:3.0.2
|    |    +--- org.checkerframework:checker-compat-qual:2.0.0 -> 2.5.3
|    |    +--- com.google.errorprone:error_prone_annotations:2.1.3 -> 2.3.1
|    |    +--- com.google.j2objc:j2objc-annotations:1.1
|    |    \--- org.codehaus.mojo:animal-sniffer-annotations:1.14
|    +--- org.checkerframework:checker-compat-qual:2.5.3
|    +--- org.checkerframework:checker-qual:2.5.3
|    +--- junit:junit:4.12 (*)
|    +--- com.googlecode.java-diff-utils:diffutils:1.3.0
|    +--- com.google.auto.value:auto-value-annotations:1.6.2
|    \--- com.google.errorprone:error_prone_annotations:2.3.1
...
+--- com.google.truth:truth:{strictly 0.42} -> 0.42 (c)
+--- com.google.guava:guava:{strictly 25.1-android} -> 25.1-android (c) // <--------- why is this listed again here at top level?

Обновление:

После обновления до Truth 0.43 IТеперь я вижу эту ошибку:

> Could not resolve all artifacts for configuration ':mymodule:debugAndroidTestRuntimeClasspath'.
   > Could not resolve com.google.guava:listenablefuture:{strictly 1.0}.
     Required by:
         project :mymodule
      > Cannot find a version of 'com.google.guava:listenablefuture' that satisfies the version constraints:
           Dependency path 'example:mymodule:unspecified' --> 'com.google.truth:truth:0.43' --> 'com.google.guava:guava:27.0.1-android' --> 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
           Constraint path 'example:mymodule:unspecified' --> 'com.google.guava:listenablefuture:{strictly 1.0}' because of the following reason: debugRuntimeClasspath uses version 1.0
           Dependency path 'example:mymodule:unspecified' --> 'example:myothermodule:unspecified' --> 'andrexampleoidx.core:core:1.1.0-alpha04' --> 'com.google.guava:listenablefuture:1.0'
           Constraint path 'example:mymodule:unspecified' --> 'com.google.guava:listenablefuture:{strictly 1.0}' because of the following reason: debugRuntimeClasspath uses version 1.0
            ...
           Dependency path 'example:mymodule:unspecified' --> 'example:myothermodule:unspecified' --> 'androidx.core:core:1.1.0-alpha04' --> 'androidx.concurrent:concurrent-futures:1.0.0-alpha02' --> 'com.google.guava:listenablefuture:1.0'
           Constraint path 'example:mymodule:unspecified' --> 'com.google.guava:listenablefuture:{strictly 1.0}' because of the following reason: debugRuntimeClasspath uses version 1.0
           ...

   > Could not resolve com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava.
     Required by:
         project :mymodule > com.google.truth:truth:0.43 > com.google.guava:guava:27.0.1-android
      > Cannot find a version of 'com.google.guava:listenablefuture' that satisfies the version constraints:
           Dependency path 'example:mymodule:unspecified' --> 'com.google.truth:truth:0.43' --> 'com.google.guava:guava:27.0.1-android' --> 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
           Constraint path 'example:mymodule:unspecified' --> 'com.google.guava:listenablefuture:{strictly 1.0}' because of the following reason: debugRuntimeClasspath uses version 1.0
           Dependency path 'example:mymodule:unspecified' --> 'example:myothermodule:unspecified' --> 'androidx.core:core:1.1.0-alpha04' --> 'com.google.guava:listenablefuture:1.0'
           ...
           Dependency path 'example:mymodule:unspecified' --> 'example:myothermodule:unspecified' --> 'androidx.core:core:1.1.0-alpha04' --> 'androidx.concurrent:concurrent-futures:1.0.0-alpha02' --> 'com.google.guava:listenablefuture:1.0'
           Constraint path 'example:mymodule:unspecified' --> 'com.google.guava:listenablefuture:{strictly 1.0}' because of the following reason: debugRuntimeClasspath uses version 1.0
           ...

   > Could not resolve com.google.guava:listenablefuture:1.0.
     Required by:
         project :mymodule > androidx.core:core:1.1.0-alpha04
         project :mymodule > androidx.concurrent:concurrent-futures:1.0.0-alpha02
      > Cannot find a version of 'com.google.guava:listenablefuture' that satisfies the version constraints:
           Dependency path 'example:mymodule:unspecified' --> 'com.google.truth:truth:0.43' --> 'com.google.guava:guava:27.0.1-android' --> 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
           Constraint path 'example:mymodule:unspecified' --> 'com.google.guava:listenablefuture:{strictly 1.0}' because of the following reason: debugRuntimeClasspath uses version 1.0
           ...
           Dependency path 'example:mymodule:unspecified' --> 'example:myothermodule:unspecified' --> 'androidx.core:core:1.1.0-alpha04' --> 'androidx.concurrent:concurrent-futures:1.0.0-alpha02' --> 'com.google.guava:listenablefuture:1.0'
           Constraint path 'example:mymodule:unspecified' --> 'com.google.guava:listenablefuture:{strictly 1.0}' because of the following reason: debugRuntimeClasspath uses version 1.0
           ...

Если я правильно понимаю:

  • Правда 0,43 зависит от гуавы 27
  • Гуава 27 зависит от 9999.0-empty, потому чтоон внутренне содержит копию ListenableFuture, а версия 9999.0-empty является "пустой".
  • другие библиотеки, такие как ядро ​​AndroidX, зависят от listenablefuture:1.0
  • При разрешенииконфликты (я должен использовать версию 1.0 или 9999.0?) Gradle выберет последнюю версию, в данном случае 9999.0.
  • Так что ядро ​​AndroidX на самом деле получает ListenableFuture из classpath через Guava, ноэто ничего не значит.
  • Однако ключевое слово strictly заставляет использовать 1.0
  • , это происходит потому, что плагин Android Gradle заставляет пути классов времени выполнения и компиляции зависеть от одной и той же версии.= ( Подробнее читайте здесь

Так что у мамыЯ застрял в том, что делать сейчас.

Ответы [ 3 ]

0 голосов
/ 25 февраля 2019

Чтобы исправить конфликт, достаточно добавить зависимость от Guava 27.Это должно автоматически (хотя хак «Версия 99 не существует», описанный в сообщении, которое вы связали ) предотвратит извлечение второй копии ListenableFuture. (Пожалуйста, дайте нам знать, если нет!)

Поскольку вы работаете над библиотекой Android, похоже, что вы хотите guava-27.0.1-android, а не -jre.

Я ничего не знаю о вашем дополнительном вопросе, извините.И извините за отсутствие ответа так долго.

0 голосов
/ 14 марта 2019

Еще одна вещь, которая, вероятно, должна «работать» - это заставить ваше приложение (не только тесты, но и все приложение) зависеть от guava:27.0.1-android.Если ваша сборка использует Proguard, она должна быть удалена (кроме ListenableFuture) во время сборки.Если вы этого не сделаете, тогда Guava - это большая зависимость, особенно для того, чтобы обойти плохое взаимодействие между нашим listenablefuture трюком и последующим плагином Android Gradle: (*

0 голосов
/ 25 февраля 2019

что-то похожее, это должно предотвратить дубликат:

implementation ("com.google.android.material:material:1.1.0-alpha03") {
    exclude group: "com.google.guava", module: "listenablefuture"
}

часть, которая обновляет библиотеку, кажется правильной:

androidTestImplementation "com.google.guava:guava:27.0.1-android"
androidTestImplementation ("com.google.truth:truth:0.42") {
    exclude group: "com.google.guava", module: "guava"
}

может принимать только без build.gradle.

...