Как настроить gradle для использования logback-classic ТОЛЬКО для юнит-тестов в Android?

У меня есть приложение для Android, которое использует slf4j + logback. Файл Gradle выглядит так:

...
compile('com.github.tony19:logback-android-core:1.1.1-6') {
    exclude group: 'ch.qos.logback.core.net'
}

compile('com.github.tony19:logback-android-classic:1.1.1-6') {
    exclude group: 'ch.qos.logback.core.net'
}

compile 'org.slf4j:slf4j-api:1.7.25'

И у меня есть logback.xml в активах /. Когда я запускаю приложение, логирование работает как положено. Недавно я решил добавить новые юнит-тесты (обычные, а не android-юнит-тесты), но увидел, что сообщения журнала не отображаются.

Я добавил следующее в файл gragle:

testCompile('ch.qos.logback:logback-classic:1.2.3') {
    exclude group: 'com.github.tony19'
}

и теперь отображаются сообщения журнала, но при каждом запуске модульных тестов я получаю это предупреждение:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/o/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.2.3/7c4f3c474fb2c041d8028740440937705ebb473a/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/o/.gradle/caches/modules-2/files-2.1/com.github.tony19/logback-android-classic/1.1.1-6/614c66c9ece69eef48c65a8558de4fd7266d9f69/logback-android-classic-1.1.1-6.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

Есть ли способ указать исключительно, какая привязка slf4j будет использоваться для регулярных запусков приложения, а какая только для модульных тестов (или любого другого решения)?

График зависимостей:

compile - Classpath for compiling the main sources.
+--- com.bolyartech.forge.android:forge-android:7.1.0
|    +--- com.bolyartech.forge:base:5.1.0
|    |    +--- org.slf4j:slf4j-api:1.7.7 -> 1.7.25
|    |    +--- com.darwinsys:hirondelle-date4j:1.5.1
|    |    +--- com.google.guava:guava:20.0
|    |    +--- javax.inject:javax.inject:1
|    |    \--- com.squareup.okhttp3:okhttp:3.1.2
|    |         \--- com.squareup.okio:okio:1.6.0
|    +--- com.google.dagger:dagger:2.9
|    |    \--- javax.inject:javax.inject:1
|    +--- com.android.support:support-annotations:25.3.1 -> 26.0.1
|    +--- javax.annotation:jsr250-api:1.0
|    +--- com.android.support.test.espresso:espresso-idling-resource:2.2.2
|    \--- net.sourceforge.streamsupport:streamsupport:1.5.1
+--- com.bolyartech.scram_sasl:scram_sasl:2.0.1
+--- com.android.support:multidex:1.0.1
+--- com.squareup:otto:1.3.8
+--- com.google.code.gson:gson:2.7
+--- com.github.franmontiel:PersistentCookieJar:v0.9.3
|    \--- com.squareup.okhttp3:okhttp:3.1.2 (*)
+--- com.github.tony19:logback-android-core:1.1.1-6
+--- com.github.tony19:logback-android-classic:1.1.1-6
|    +--- com.github.tony19:logback-android-core:1.1.1-6
|    \--- com.github.tony19:apktool-lib:1.4.4-3
|         \--- com.google.android:android:2.1_r1
|              +--- commons-logging:commons-logging:1.1.1
|              +--- org.apache.httpcomponents:httpclient:4.0.1
|              |    +--- org.apache.httpcomponents:httpcore:4.0.1
|              |    +--- commons-logging:commons-logging:1.1.1
|              |    \--- commons-codec:commons-codec:1.3
|              +--- org.khronos:opengl-api:gl1.1-android-2.1_r1
|              +--- xerces:xmlParserAPIs:2.6.2
|              \--- xpp3:xpp3:1.1.4c
+--- ch.acra:acra:4.7.0
|    \--- com.android.support:support-v4:23.0.1 -> 26.0.1
|         +--- com.android.support:support-compat:26.0.1
|         |    \--- com.android.support:support-annotations:26.0.1
|         +--- com.android.support:support-media-compat:26.0.1
|         |    +--- com.android.support:support-annotations:26.0.1
|         |    \--- com.android.support:support-compat:26.0.1 (*)
|         +--- com.android.support:support-core-utils:26.0.1
|         |    +--- com.android.support:support-annotations:26.0.1
|         |    \--- com.android.support:support-compat:26.0.1 (*)
|         +--- com.android.support:support-core-ui:26.0.1
|         |    +--- com.android.support:support-annotations:26.0.1
|         |    \--- com.android.support:support-compat:26.0.1 (*)
|         \--- com.android.support:support-fragment:26.0.1
|              +--- com.android.support:support-compat:26.0.1 (*)
|              +--- com.android.support:support-core-ui:26.0.1 (*)
|              \--- com.android.support:support-core-utils:26.0.1 (*)
+--- org.slf4j:slf4j-api:1.7.25
+--- javax.inject:javax.inject:1
+--- javax.annotation:jsr250-api:1.0
+--- com.google.dagger:dagger:2.9 (*)
\--- com.android.support:appcompat-v7:26.0.1
     +--- com.android.support:support-annotations:26.0.1
     +--- com.android.support:support-v4:26.0.1 (*)
     +--- com.android.support:support-vector-drawable:26.0.1
     |    +--- com.android.support:support-annotations:26.0.1
     |    \--- com.android.support:support-compat:26.0.1 (*)
     \--- com.android.support:animated-vector-drawable:26.0.1
          +--- com.android.support:support-vector-drawable:26.0.1 (*)
          \--- com.android.support:support-core-ui:26.0.1 (*)


testCompile - Classpath for compiling the test sources.
+--- ch.qos.logback:logback-classic:1.2.3
|    +--- ch.qos.logback:logback-core:1.2.3
|    \--- org.slf4j:slf4j-api:1.7.25
+--- junit:junit:4.12
|    \--- org.hamcrest:hamcrest-core:1.3
\--- org.mockito:mockito-core:1.10.19
     +--- org.hamcrest:hamcrest-core:1.1 -> 1.3
     \--- org.objenesis:objenesis:2.1

4 ответа

Решение

С Android Gradle Plugin 3 и выше, попробуйте использовать следующее:

implementation 'org.slf4j:slf4j-api:1.7.25'   
runtimeOnly 'com.github.tony19:logback-android-core:1.1.1-6'

Область зависимостей

В старой версии gradle область зависимостей компиляции будет включена во все пути классов проектов, включая компиляцию, время выполнения, компиляцию теста и выполнение теста. Таким образом, две реализации класса SLF4J будут включены в выполнение теста.

SLF4J Binding

И поскольку реализация привязок SLF4J, две привязки будут вызывать предупреждение, SLF4J будет случайным образом выбирать привязку, в данном случае, а не logback.

Решение

Таким образом, единственный способ решить эту проблему - исключить logback-android из вашего тестового пути к классам.

В новой версии Gradle (4.0.2) мы определяем logback-android в runtimeElements чтобы избежать использования тестовой средой. В старой версии кажется, что мы не можем решить эту проблему с Gradle.

ссылка

Вы должны исключить его на корневом уровне вместо классической зависимости logback:

configurations {
    testCompile.exclude group: 'com.github.tony19'
}

Исключить библиотеку tony19 из тестового пути к классам с помощью

      configurations {
  testImplementation.exclude group: 'com.github.tony19'
  //with testCompile the library is not used for compilation but used for running tests
}

dependencies {
  //logging
  implementation 'org.slf4j:slf4j-api:1.7.30'
  runtimeOnly 'com.github.tony19:logback-android:2.0.0'
  testImplementation group: 'ch.qos.logback', name: 'logback-classic', version:  '1.2.11'
}

С использованием testCompile.excludeвсе равно предупредите

      SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/raiser/.gradle/caches/transforms-3/5db974f19df3b652be1c75410514efb8/transformed/jetified-logback-classic-1.2.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/raiser/.gradle/caches/transforms-3/f97ca29862548c3aa25d47e0ab6abbab/transformed/jetified-logback-android-2.0.0-runtime.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/raiser/.gradle/caches/transforms-3/17f8528b15b95f4e98b73ee7482c4884/transformed/jetified-logback-android-2.0.0/jars/classes.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
Другие вопросы по тегам