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

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

Итак, я добавил в свой файл 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;

person rindress    schedule 21.08.2014    source источник
comment
Можете выложить трассировку стека?   -  person yogurtearl    schedule 22.08.2014
comment
Хорошо, я обновил публикацию с помощью вывода logcat. Я заметил, что есть ряд записей, в которых вопросы поддержки v7 не решены. Я предполагаю, что это большая подсказка, но я все еще не могу найти ничего, что могло бы помочь.   -  person rindress    schedule 26.08.2014
comment
Похоже, что это может иметь какое-то отношение к тому, как вы включаете библиотеки поддержки v7 и v4. Вы должны убедиться, что они включены только в ваше приложение, а не в тестовый APK.   -  person yogurtearl    schedule 27.08.2014
comment
Спасибо, я ценю, что вы на это посмотрели. Я добавил зависимости, которые у меня есть, и «верю», что исключил поддержку и совместимость приложений.   -  person rindress    schedule 27.08.2014
comment
На какой версии Android это происходит? Вы пользуетесь прогардом?   -  person yogurtearl    schedule 27.08.2014
comment
Также, для справки, здесь есть аналогичная трассировка стека: stackoverflow.com/questions/15014186/   -  person yogurtearl    schedule 27.08.2014
comment
Я тестирую образ Genymotion 4.4.2, и он не использует proguard.   -  person rindress    schedule 27.08.2014


Ответы (3)


Хорошо, я смог решить эту проблему, основываясь на ряде ссылок. Прежде всего спасибо 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/

person rindress    schedule 04.09.2014
comment
ЭТО! Большое спасибо. Мне потребовалось несколько часов, чтобы понять, что происходит, но мне просто нужно было добавить несколько исключений в свой build.gradle. - person rrbrambley; 26.10.2016

Решения:

  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.

person yogurtearl    schedule 31.08.2014
comment
Итак, я внес предложенные вами изменения и все еще получаю ошибку NoClassDefinedError? Я удалил fest и добавил assertj - person rindress; 03.09.2014

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

person yuval    schedule 20.08.2015