Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Выполнение тестов с использованием gradle или внутри студии Android приводит к NoClassDefFoundError

Автор вопроса: rindressОтветов: 3

Однако я знаю, что задавать этот тип вопросов без конкретики очень сложно; проект, в котором возникла проблема, является проприетарным, и мне не удалось воспроизвести проблему в каком-либо другом проекте.

Итак, я добавил в свой файл build.gradle следующее:

androidTestCompile('com.jakewharton.espresso:espresso:1.1-r3') {
    exclude group: 'com.square.dagger'
}
androidTestCompile('com.jakewharton.espresso:espresso-support-v4:1.1-r3') {
    exclude group: 'com.android.support'
}

У меня также определены два вкуса продукта, ни один из них не работает. У меня есть тестовый класс:

   public class MainActivityInstrumentationTest extends ActivityInstrumentationTestCase2<MainActivity> {
       private MainActivity myActivity;
       private Spinner spinner;

       public MainActivityInstrumentationTest() {
         super(MainActivity.class);
        }
        protected void setUp() throws Exception {
          super.setUp();

          myActivity = getActivity();
          spinner = (Spinner)myActivity.findViewById(R.id.watch_category);
        }

        public void testTextView() {
          assertOnScreen(myActivity.getWindow().getDecorView(), spinner);
        }
    }

Теперь в студии он находит MainActivity.class нормально и добавляет правильный импорт. Тем не мение; когда я запускаю тест, конструктор выдает исключение, что полный путь к классу .class не найден. Я пробовал запускать gradle с --debug и не вижу ничего необычного. Сгенерированный файл apk имеет classes.dex, и, используя dex2jar, я вижу там MainActivity.class. Итак, на данный момент я немного не понимаю, почему файл класса не найден во время выполнения теста. Есть ли у кого-нибудь другие методы, которыми я могу попытаться отладить эту ситуацию, как я уже сказал, у меня есть другие проекты, которые работают нормально, и я не могу изменить их, чтобы продемонстрировать такое поведение.

Любая помощь в этом будет принята с благодарностью.

РЕДАКТИРОВАТЬ: Полная трассировка из logcat

W/dalvikvm( 4371): Class resolved by unexpected DEX: Landroid/support/v7/app/ActionBarActivity;(0xa501f5e8):0x94c6a000 ref [Landroid/support/v4/app/FragmentActivity;] Landroid/support/v4/app/FragmentActivity;(0xa501f5e8):0x9528b000
W/dalvikvm( 4371): (Landroid/support/v7/app/ActionBarActivity; had used a different Landroid/support/v4/app/FragmentActivity; during pre-verification)
W/dalvikvm( 4371): Unable to resolve superclass of Landroid/support/v7/app/ActionBarActivity; (282)
W/dalvikvm( 4371): Link of class 'Landroid/support/v7/app/ActionBarActivity;' failed
W/dalvikvm( 4371): Unable to resolve superclass of Lcom/mycompany/mypackage/MainActivity; (763)
W/dalvikvm( 4371): Link of class 'Lcom/mycompany/mypackage/MainActivity;' failed
E/dalvikvm( 4371): Could not find class 'com.mycompany.myapp.MainActivity', referenced from method com.mycompany.myapp.tests.MainActivityInstrumentationTest.<init>
W/dalvikvm( 4371): VFY: unable to resolve const-class 2880 (Lcom/mycompany/mypackage/MainActivity;) in Lcom/mycompany/mypackage/tests/MainActivityInstrumentationTest;
D/dalvikvm( 4371): VFY: replacing opcode 0x1c at 0x0000
W/dalvikvm( 4371): Class resolved by unexpected DEX: Landroid/support/v7/app/ActionBarActivity;(0xa501f5e8):0x94c6a000 ref [Landroid/support/v4/app/FragmentActivity;] Landroid/support/v4/app/FragmentActivity;(0xa501f5e8):0x9528b000
W/dalvikvm( 4371): (Landroid/support/v7/app/ActionBarActivity; had used a different Landroid/support/v4/app/FragmentActivity; during pre-verification)
W/dalvikvm( 4371): Unable to resolve superclass of Landroid/support/v7/app/ActionBarActivity; (282)
W/dalvikvm( 4371): Link of class 'Landroid/support/v7/app/ActionBarActivity;' failed
W/dalvikvm( 4371): Unable to resolve superclass of Lcom/mycompany/mypackage/MainActivity; (763)
W/dalvikvm( 4371): Link of class 'Lcom/mycompany/mypackage/MainActivity;' failed
E/dalvikvm( 4371): Could not find class 'com.mycompany.myapp.MainActivity', referenced from method com.mycompany.myapp.tests.MainActivityInstrumentationTest.setUp
W/dalvikvm( 4371): VFY: unable to resolve check-cast 2880 (Lcom/mycompany/mypackage/MainActivity;) in Lcom/mycompany/mypackage/tests/MainActivityInstrumentationTest;
D/dalvikvm( 4371): VFY: replacing opcode 0x1f at 0x0007
D/dalvikvm( 4371): GC_FOR_ALLOC freed 261K, 10% free 3376K/3712K, paused 2ms, total 2ms
W/dalvikvm( 4371): Class resolved by unexpected DEX: Landroid/support/v7/app/ActionBarActivity;(0xa501f5e8):0x94c6a000 ref [Landroid/support/v4/app/FragmentActivity;] Landroid/support/v4/app/FragmentActivity;(0xa501f5e8):0x9528b000
W/dalvikvm( 4371): (Landroid/support/v7/app/ActionBarActivity; had used a different Landroid/support/v4/app/FragmentActivity; during pre-verification)
W/dalvikvm( 4371): Unable to resolve superclass of Landroid/support/v7/app/ActionBarActivity; (282)
W/dalvikvm( 4371): Link of class 'Landroid/support/v7/app/ActionBarActivity;' failed
W/dalvikvm( 4371): Unable to resolve superclass of Lcom/mycompany/mypackage/MainActivity; (763)
W/dalvikvm( 4371): Link of class 'Lcom/mycompany/mypackage/MainActivity;' failed
W/dalvikvm( 4371): Class resolved by unexpected DEX: Landroid/support/v7/app/ActionBarActivity;(0xa501f5e8):0x94c6a000 ref [Landroid/support/v4/app/FragmentActivity;] Landroid/support/v4/app/FragmentActivity;(0xa501f5e8):0x9528b000
W/dalvikvm( 4371): (Landroid/support/v7/app/ActionBarActivity; had used a different Landroid/support/v4/app/FragmentActivity; during pre-verification)
W/dalvikvm( 4371): Unable to resolve superclass of Landroid/support/v7/app/ActionBarActivity; (282)
W/dalvikvm( 4371): Link of class 'Landroid/support/v7/app/ActionBarActivity;' failed
W/dalvikvm( 4371): Unable to resolve superclass of Lcom/mycompany/mypackage/MainActivity; (763)
W/dalvikvm( 4371): Link of class 'Lcom/mycompany/mypackage/MainActivity;' failed
I/dalvikvm( 4371): Could not find method com.mycompany.myapp.MainActivity.getWindow, referenced from method com.mycompany.myapp.tests.MainActivityInstrumentationTest.testTextView
W/dalvikvm( 4371): VFY: unable to resolve virtual method 21012: Lcom/mycompany/mypackage/MainActivity;.getWindow ()Landroid/view/Window;
D/dalvikvm( 4371): VFY: replacing opcode 0x6e at 0x0002
D/dalvikvm( 4371): GC_FOR_ALLOC freed 348K, 11% free 3541K/3964K, paused 2ms, total 2ms
I/System.out( 4371): Sending WAIT chunk
I/dalvikvm( 4371): Debugger is active
I/System.out( 4371): Debugger has connected
I/System.out( 4371): waiting for debugger to settle...
I/System.out( 4371): waiting for debugger to settle...
I/System.out( 4371): waiting for debugger to settle...
I/System.out( 4371): waiting for debugger to settle...
I/System.out( 4371): waiting for debugger to settle...
I/System.out( 4371): waiting for debugger to settle...
I/System.out( 4371): waiting for debugger to settle...
I/System.out( 4371): debugger has settled (1483)
I/TestRunner( 4371): started: warning(junit.framework.TestSuite$1)
I/GoogleInstr( 4371): Activities that are still in CREATED to PAUSED: 0
I/TestRunner( 4371): failed: warning(junit.framework.TestSuite$1)
I/TestRunner( 4371): ----- begin exception -----
I/TestRunner( 4371):
I/TestRunner( 4371): junit.framework.AssertionFailedError: Exception in constructor: testTextView (java.lang.NoClassDefFoundError: com.mycompany.myapp.MainActivity
I/TestRunner( 4371):  at com.mycompany.myapp.tests.MainActivityInstrumentationTest.<init>(MainActivityInstrumentationTest.java:19)
I/TestRunner( 4371):  at java.lang.reflect.Constructor.constructNative(Native Method)
I/TestRunner( 4371):  at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
I/TestRunner( 4371):  at junit.framework.TestSuite.createTest(TestSuite.java:61)
I/TestRunner( 4371):  at junit.framework.TestSuite.addTestMethod(TestSuite.java:294)
I/TestRunner( 4371):  at junit.framework.TestSuite.addTestsFromTestCase(TestSuite.java:150)
I/TestRunner( 4371):  at junit.framework.TestSuite.<init>(TestSuite.java:129)
I/TestRunner( 4371):  at junit.runner.BaseTestRunner.getTest(BaseTestRunner.java:118)
I/TestRunner( 4371):  at android.test.AndroidTestRunner.getTest(AndroidTestRunner.java:149)
I/TestRunner( 4371):  at android.test.AndroidTestRunner.setTestClassName(AndroidTestRunner.java:57)
I/TestRunner( 4371):  at android.test.suitebuilder.TestSuiteBuilder.addTestClassByName(TestSuiteBuilder.java:80)
I/TestRunner( 4371):  at android.test.InstrumentationTestRunner.parseTestClass(InstrumentationTestRunner.java:443)
I/TestRunner( 4371):  at android.test.InstrumentationTestRunner.parseTestClasses(InstrumentationTestRunner.java:424)
I/TestRunner( 4371):  at android.test.InstrumentationTestRunner.onCreate(InstrumentationTestRunner.java:370)
I/TestRunner( 4371):  at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onCreate(GoogleInstrumentationTestRunner.java:114)
I/TestRunner( 4371):  at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4335)
I/TestRunner( 4371):  at android.app.ActivityThread.access$1500(ActivityThread.java:135)
I/TestRunner( 4371):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
I/TestRunner( 4371):  at android.os.Handler.dispatchMessage(Handler.java:102)
I/TestRunner( 4371):  at android.os.Looper.loop(Looper.java:136)
I/TestRunner( 4371):  at android.app.ActivityThread.main(ActivityThread.java:5017)
I/TestRunner( 4371):  at java.lang.reflect.Method.invokeNative(Native Method)
I/TestRunner( 4371):  at java.lang.reflect.Method.invoke(Method.java:515)
I/TestRunner( 4371):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
I/TestRunner( 4371):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
I/TestRunner( 4371):  at dalvik.system.NativeStart.main(Native Method)
I/TestRunner( 4371): )
I/TestRunner( 4371):  at junit.framework.Assert.fail(Assert.java:50)
I/TestRunner( 4371):  at junit.framework.TestSuite$1.runTest(TestSuite.java:97)
I/TestRunner( 4371):  at junit.framework.TestCase.runBare(TestCase.java:134)
I/TestRunner( 4371):  at junit.framework.TestResult$1.protect(TestResult.java:115)
I/TestRunner( 4371):  at junit.framework.TestResult.runProtected(TestResult.java:133)
I/TestRunner( 4371):  at junit.framework.TestResult.run(TestResult.java:118)
I/TestRunner( 4371):  at junit.framework.TestCase.run(TestCase.java:124)
I/TestRunner( 4371):  at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
I/TestRunner( 4371):  at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
I/TestRunner( 4371):  at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)
I/TestRunner( 4371):  at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onStart(GoogleInstrumentationTestRunner.java:167)
I/TestRunner( 4371):  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)
I/TestRunner( 4371): ----- end exception -----
I/TestRunner( 4371): finished: warning(junit.framework.TestSuite$1)
I/GoogleInstr( 4371): Activities that are still in CREATED to PAUSED: 0
I/GoogleInstr( 4371): waitForActivitiesToComplete() took: 0ms
D/AndroidRuntime( 4361): Shutting down VM

Изменить: зависимости build.gradle

dependencies {
    compile 'com.mcxiaoke.volley:library-aar:1.0.+'
    compile 'com.android.support:support-v4:19.0.+'
    compile 'com.android.support:appcompat-v7:19.0.+'
    compile 'com.google.android.gms:play-services:4.2.42'
    compile 'com.arcbees:facebook:1.1.1'
    compile 'com.facebook:facebook-android-sdk:3.5.2@aar'
    compile 'com.j256.ormlite:ormlite-android:4.47'
    compile 'com.j256.ormlite:ormlite-core:4.47'
    compile 'com.google.code.gson:gson:2.2.4'
    compile 'org.slf4j:slf4j-api:1.7.5'
    compile 'com.github.tony19:logback-android-classic:1.1.1-3'
    compile 'com.crashlytics.android:crashlytics:1.+'
    compile 'com.nineoldandroids:library:2.4.0'
    compile 'com.squareup.dagger:dagger:1.0.1'
    compile 'com.squareup.dagger:dagger-compiler:1.0.1'
    compile 'com.jakewharton:butterknife:1.3.2'
    compile 'com.actionbarsherlock:viewpagerindicator:2.4.1'
    compile 'com.squareup:otto:1.3.4'
    compile 'com.squareup.picasso:picasso:1.1.1'
    compile 'com.squareup.retrofit:retrofit:1.2.2'
    compile 'com.github.machinarius:preferencefragment:0.1.1'
    compile files('libs/cwac-wakefulintentservice.jar')
    compile files('libs/libGoogleAnalyticsServices.jar')
    compile files('libs/android-switch-backport.jar')
    compile files('libs/google-api-client-googleapis-1.4.1-beta.jar')

    androidTestCompile 'com.squareup:fest-android:1.0.+'
    androidTestCompile('com.jakewharton.espresso:espresso:1.1-r3') {
        exclude group: 'com.square.dagger'
    }
    androidTestCompile('com.jakewharton.espresso:espresso-support-v4:1.1-r3') {
        exclude group:'com.android.support', module:'support-v4'
        exclude group:'com.android.support', module:'appcompat-v7'
    }
}

Обновление: после обновления зависимостей я все еще получаю NoClassDefFoundError, а в logcat я вижу

W/dalvikvm( 3373): Class resolved by unexpected DEX: Lcom/mycompany/mypackage/MainActivity;(0xa50a6d18):0x94ba7000 ref [Landroid/support/v7/app/ActionBarActivity;] Landroid/support/v7/app/ActionBarActivity;(0xa50a6d18):0x95318000
W/dalvikvm( 3373): (Lcom/mycompany/mypackage/MainActivity; had used a different Landroid/support/v7/app/ActionBarActivity; during pre-verification)
W/dalvikvm( 3373): Unable to resolve superclass of Lcom/mycompany/mypackage/MainActivity; (786)
W/dalvikvm( 3373): Link of class 'Lcom/mycompany/mypackage/MainActivity;' failed
E/dalvikvm( 3373): Could not find class 'com.ping4.ping4alerts.MainActivity', referenced from method com.ping4.ping4alerts.tests.MainActivityInstrumentationTest.<init>
W/dalvikvm( 3373): VFY: unable to resolve const-class 3298 (Lcom/mycompany/mypackage/MainActivity;) in Lcom/mycompany/mypackage/tests/MainActivityInstrumentationTest;
  • Можете выложить трассировку стека? yogurtearl 22.08.2014
  • Хорошо, я обновил публикацию с помощью вывода logcat. Я заметил, что есть ряд записей, в которых вопросы поддержки v7 не решены. Я предполагаю, что это большая подсказка, но я все еще не могу найти ничего, что могло бы помочь. rindress 26.08.2014
  • Похоже, что это может иметь какое-то отношение к тому, как вы включаете библиотеки поддержки v7 и v4. Вы должны убедиться, что они включены только в ваше приложение, а не в тестовый APK. yogurtearl 27.08.2014
  • Спасибо, я ценю, что вы на это посмотрели. Я добавил зависимости, которые у меня есть, и "верю", что исключил поддержку и совместимость приложений. rindress 27.08.2014
  • На какой версии Android это происходит? Вы пользуетесь прогардом? yogurtearl 27.08.2014
  • Также, для справки, здесь есть аналогичная трассировка стека: stackoverflow.com/questions/15014186/ yogurtearl 27.08.2014

android-studioandroidandroid-gradle-pluginandroid-espresso

Ответы

Ответ 1 · рейтинг 5 · rindress

Хорошо, я смог решить эту проблему, основываясь на ряде ссылок. Прежде всего спасибо yogurtearl за всю информацию. По существу возник ряд вопросов. В конце концов, NoClassDefError оказался отвлекающим маневром. Настоящая проблема была в выводе logcat, опубликованном после первоначального вопроса. Это указывало на то, что были проблемы при попытке решить проблему после предварительной обработки.

Поэтому я настоятельно рекомендую людям запускать команду gradle -q dependencies. Выполнение этого даст вам массу информации. Основываясь на этом выводе, я смог определить, что я не исключаю вещи, поэтому было включено несколько версий, создавая проблему во время выполнения. Другая вещь, которая изначально была неправильной, заключалась в том, что у меня была exclude group: 'com.square.dagger' опечатка. Должно было быть exclude group: 'com.squareup.dagger'. Я надеюсь, что кто-то столкнется с этим, и это сэкономит им время, пытаясь отследить проблемы. Следующая статья была очень полезна в решении этой проблемы: http://blog.gaku.net/multiple-dex-files-define-with-gradle/

Ответ 2 · рейтинг 3 · yogurtearl

Решения:

  1. Измените зависимость для fest-android на версию 1.0.7

    androidTestCompile 'com.squareup: fest-android: 1.0.7'

  2. Исключите support-v4 из fest-android:

    androidTestCompile ('com.squareup: fest-android: 1.0. +') {исключить группу: 'com.android.support', модуль: 'support-v4'}

  3. Обновитесь до AssertJ-Android (рекомендуется). Fest-Android был заменен AssertJ-Android (http://square.github.io/assertj-android/)

    androidTestCompile 'com.squareup.assertj: assertj-android: 1.0.0'

Справочная информация:

Проблема в том, что com.squareup: fest-android: 1.0. + Преобразуется в com.squareup: fest-android: 1.0.8.

Версия 1.0.8 включает зависимость gradle от com.android.support:support-v4:19.1.+. См. Здесь: https://github.com/square/assertj-android/blob/1.0.8/build.gradle

Это было переведено в зависимость области "компиляции" от support-v4 в maven pom. См. Здесь: http://repo1.maven.org/maven2/com/squareup/fest-android/1.0.8/fest-android-1.0.8.pom

Кстати, версия 1.0.7 была построена с помощью Maven (не gradle) и имеет "предоставленную" зависимость области действия для support-v4, поэтому это ведет себя по-другому. См. Здесь: http://repo1.maven.org/maven2/com/squareup/fest-android/1.0.7/fest-android-1.0.7.pom

Кроме того, Android Lint выдает предупреждения для " Динамическая версия Gradle ".

"Использование + в зависимостях позволяет автоматически выбирать последнюю доступную версию, а не конкретную именованную версию. Однако это не рекомендуется; ваши сборки не воспроизводятся; возможно, вы тестировали версию, которая немного отличается от той, которая использовалась сервером сборки. . "

В этом случае использование "+" для fest-android привело бы к сбою вашей сборки без каких-либо изменений с вашей стороны, когда был выпущен fest-android v1.0.8.

Ответ 3 · yuval

У меня была аналогичная проблема, и я понял, что столкнулся с ограничения библиотеки поддержки multidex, которую я использовал, чтобы преодолеть ограничение в 65K методов Android. На самом деле нет хорошего решения для этого, кроме как попытаться вырвать неиспользуемые библиотеки из вашего проекта, использовать proguard или установить minSdkVersion на 21. Надеюсь, это поможет любому, кто в конечном итоге столкнется с аналогичной проблемой.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы