Robolectric与Google APIs - AnnotationFormatError

3
我尝试设置Robolectric与我的项目编译的Google API目标一起工作,但无法使其正常工作。我尝试了各种方法,并使用deckard-gradle分离出了问题:当我下载Deckard项目时,一切正常,并且样例测试可以成功运行。但是,当我在我的Gradle文件中改变compileSdk设置为Google Inc.:Google APIs:19时,在运行测试时出现AnnotationFormatError。
   java.lang.annotation.AnnotationFormatError: Invalid default: public abstract java.lang.Class org.robolectric.annotation.Config.application()
    at java.lang.reflect.Method.getDefaultValue(Method.java:747)
    at sun.reflect.annotation.AnnotationType.<init>(AnnotationType.java:128)
    at sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:85)
    at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:263)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:117)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:70)
    at java.lang.Class.initAnnotationsIfNecessary(Class.java:3271)
    at java.lang.Class.getAnnotations(Class.java:3240)
    at org.junit.runner.Description.createSuiteDescription(Description.java:123)
    at org.junit.internal.runners.ErrorReportingRunner.getDescription(ErrorReportingRunner.java:25)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:83)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:69)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:48)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:105)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)
    at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

这是我设置的一些相关代码片段:

build.gradle

    buildscript {
        repositories {
            mavenCentral()
        }

        dependencies {
            classpath 'com.android.tools.build:gradle:0.13.+'
            classpath 'org.robolectric:robolectric-gradle-plugin:0.13.+'
        }
    }

    allprojects {
        repositories {
            mavenCentral()
        }
    }

    apply plugin: 'android'
    apply plugin: 'robolectric'

    android {
        packagingOptions {
            exclude 'LICENSE.txt'
            exclude 'META-INF/LICENSE'
            exclude 'META-INF/LICENSE.txt'
            exclude 'META-INF/NOTICE'
        }
        compileSdkVersion "Google Inc.:Google APIs:19"
        buildToolsVersion "19.1.0"

        defaultConfig {
            minSdkVersion 18
            targetSdkVersion 18
            versionCode 2
            versionName "1.0.0-SNAPSHOT"
            testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
        }
        buildTypes {
            release {
                runProguard false
            }
        }

        sourceSets {
            androidTest {
                setRoot('src/test')
            }
        }
    }

    robolectric {
        include '**/*Test.class'
        exclude '**/espresso/**/*.class'
    }

    dependencies {
        repositories {
            mavenCentral()
        }
        // Espresso
        androidTestCompile files('lib/espresso-1.1.jar', 'lib/testrunner-1.1.jar', 'lib/testrunner-runtime-1.1.jar')
        androidTestCompile 'com.google.guava:guava:14.0.1'
        androidTestCompile 'com.squareup.dagger:dagger:1.1.0'
        androidTestCompile 'org.hamcrest:hamcrest-integration:1.1'
        androidTestCompile 'org.hamcrest:hamcrest-core:1.1'
        androidTestCompile 'org.hamcrest:hamcrest-library:1.1'

        androidTestCompile('junit:junit:4.11') {
            exclude module: 'hamcrest-core'
        }
        androidTestCompile('org.robolectric:robolectric:2.4') {
            exclude module: 'classworlds'
            exclude module: 'commons-logging'
            exclude module: 'httpclient'
            exclude module: 'maven-artifact'
            exclude module: 'maven-artifact-manager'
            exclude module: 'maven-error-diagnostics'
            exclude module: 'maven-model'
            exclude module: 'maven-project'
            exclude module: 'maven-settings'
            exclude module: 'plexus-container-default'
            exclude module: 'plexus-interpolation'
            exclude module: 'plexus-utils'
            exclude module: 'wagon-file'
            exclude module: 'wagon-http-lightweight'
            exclude module: 'wagon-provider-api'
        }
        androidTestCompile 'com.squareup:fest-android:1.0.+'
    }

    apply plugin: 'idea'

    idea {
        module {
            testOutputDir = file('build/test-classes/debug')
        }
    }

我的测试类:

@Config(manifest = "./src/main/AndroidManifest.xml", emulateSdk = 18)
@RunWith(RobolectricTestRunner.class)
public class DeckardActivityRobolectricTest {

    @Test
    public void testSomething() throws Exception {
        Activity activity = Robolectric.buildActivity(DeckardActivity.class).create().get();
        assertTrue(activity != null);
    }
}

我还按照 robolectric 的指示将地图和支持库安装到了本地的maven仓库中。
我的设置可能有什么问题呢?

我不确定,但也许你不应该更改编译SDK,而是添加额外的依赖项 compile 'com.google.android.gms:play-services:6.1.71' - Eugen Martynov
2个回答

0
出于各种原因,我已经放弃了上述方法,转而将我的Robolectric测试保留在Gradle子模块中。您可以找到我写的一篇关于为什么我朝这个方向转变的博客文章,以及一个展示如何做到这一点的deckard-gradle项目的分支here。由于Robolectric只支持SDK版本18及以下,因此该项目还具有修改后的RobolectricTestRunner,它强制执行此操作,而不需要注释来模拟较低的SDK版本。

谢谢。我无法完全找到问题的根源,但我猜测可能是冲突的依赖关系或类似的问题。我同意你的观点,使用子模块要容易得多。非常感谢您的Deckard分支,它可以很好地与Google APIs配合使用。当然,与我的robolectric经验一致,解决了这个问题后,我遇到了其他一些问题,目前卡在了actionbarsherlock和它的主题上。但我最终会登上山顶的,即使他们向我扔石头 ;) - ct_rob
@jdonmoyer 你是否已经检查了你的方法,以确保它与Android Studio 1.1.0兼容,并添加了单元测试支持 - http://tools.android.com/tech-docs/unit-testing-support? - bogumil
@bogumil,我目前正在使用基于我在GitHub上的示例的项目,使用Android Studio 1.1.0,但我还没有调查内置的单元测试支持。如果您成功了,请随时提交一个补丁。 - jdonmoyer

0
对我来说问题在于我的 gradle 文件中的 compileSdkVersion 设置为 21,而 Robolectric 官方不支持 21(他们现在正在使用版本 3),所以我将其更改为 18,现在它可以工作了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接