使用gradle或android studio内部运行测试会导致NoClassDefFoundError

时间:2014-08-21 19:05:17

标签: android android-studio android-gradle android-espresso

我知道,在没有具体细节的情况下提出这类问题非常困难;有问题的项目是专有的,我无法在任何其他项目中重现该问题。

所以我已将以下内容添加到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'
    }
}

更新: 在更新了dependecies后,我仍然得到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;

3 个答案:

答案 0 :(得分:5)

好的,所以我能够根据一些参考资料来解决这个问题。首先感谢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/

答案 1 :(得分:3)

解决方案:

  1. 将fest-android的依赖关系更改为版本1.0.7

    androidTestCompile'c​​om.squareup:fest-android:1.0.7'

  2. 从fest-android:

    中排除support-v4

    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'c​​om.squareup.assertj:assertj-android:1.0.0'

  4. 背景资料:

    问题是“com.squareup:fest-android:1.0。+”正在解析为com.squareup:fest-android:1.0.8。

    版本1.0.8包含对'com.android.support:support-v4:19.1.+'的gradle依赖。见这里:https://github.com/square/assertj-android/blob/1.0.8/build.gradle

    这被转换为maven pom中support-v4的“编译”范围依赖。见这里:http://repo1.maven.org/maven2/com/squareup/fest-android/1.0.8/fest-android-1.0.8.pom

    BTW,版本1.0.7是built with 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 Dynamic Version"的警告。

    “在依赖项中使用+可让您自动获取最新的可用版本,而不是特定的命名版本。但是,建议不要这样做;您的构建版本不可重复;您可能已经进行了稍微不同的测试版本比构建服务器使用的版本。“

    在这种情况下,当fest-android v1.0.8发布时,在fest-android中使用'+'会导致你的构建在没有任何变化的情况下中断。

答案 2 :(得分:0)

我遇到了类似的问题,最后我发现我遇到了limitations of the multidex support library,我正在使用它来克服Android的65K方法限制。除了试图从你的项目中删除未使用的库,使用proguard或将你的minSdkVersion设置为21之外,还没有一个很好的解决方案。希望这可以帮助那些最终遇到类似问题的人。