Android Studio上的自定义Android sdk和单元测试

Android Studio上的自定义Android sdk和单元测试,android,unit-testing,android-gradle-plugin,Android,Unit Testing,Android Gradle Plugin,我正在尝试使用Android Studio 2.2.2中的定制Android Sdk和com.Android.tools.build:gradle:2.2进行单元测试。但是我不断地遇到一些错误,无法克服它们,所以我想请求您的帮助。让我解释一下我做了什么,试着看看你是否能找到答案并帮助我 我用Android6(sdk 23)从Nexus5x中提取类,制作了一个定制的android.jar。这个jar包含隐藏的方法和内部类 完整自定义SDK 第一次尝试是创建一个完整的SDK。为此,我下载了SDK,安

我正在尝试使用Android Studio 2.2.2中的定制Android Sdk和com.Android.tools.build:gradle:2.2进行单元测试。但是我不断地遇到一些错误,无法克服它们,所以我想请求您的帮助。让我解释一下我做了什么,试着看看你是否能找到答案并帮助我

我用Android6(sdk 23)从Nexus5x中提取类,制作了一个定制的android.jar。这个jar包含隐藏的方法和内部类

完整自定义SDK 第一次尝试是创建一个完整的SDK。为此,我下载了SDK,安装了版本23,并用我的自定义jar替换了新的_SDK/platform/android-23/android.jar

在Android Studio中,我可以执行诸如assemble或install之类的任务来生成apk,但当我执行unitTest或任何包含“:app:mockableAndroidJar”任务的任务时,我会出现以下错误:

Execution failed for task ':app:mockableAndroidJar' > java.lang.NullPointerException (no error message)
我想我之所以会出现这个错误,是因为定制sdk在方法中包含实现,并且没有像原始的android.jar那样的存根

自定义类似SDK的JAR依赖项 我尝试的第二个尝试是使用原始sdk并添加扩展的自定义sdk,如依赖项jar。在本例中,我在app build.gradle中添加jar,如下所示:

dependencies {
   ...
   provided files('libs/android-full-23-nexus5x.jar')
   ...
}
AndroidStudio显示隐藏方法和常量的编译错误,因为无法解析符号,但它适用于内部类

问题是Android Sdk覆盖了我的自定义jar。为了解决这个问题,我在app.iml中更改了依赖项的顺序,因此:

...
<orderEntry type="library" exported="" name="android-full-23-nexus5x" level="project" />
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK"/>
...
通过添加root build.gradle解决了这个问题:

allprojects {
   ...
gradle.projectsEvaluated {
    tasks.withType(JavaCompile) {
        options.compilerArgs.add("-Xbootclasspath/p:app/libs/android-full-23-nexus5x.jar")
       }
    }
}
同步、清理和重建后,组装和安装任务可以工作,仅适用于实际的构建类型,但它可以工作

现在,我在没有模拟的情况下执行单元测试,如:

public class EmailValidatorTest {
    @Test
    public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
        assertTrue(EmailValidator.isValidEmail("name@email.com"));
    }
}
这工作正常,但当我需要使用mock执行unitTest时,会失败:

public class MockUnitTest {

    private static final String FAKE_STRING = "my_app_name";

    @Mock
    Context mMockContext;

    @Test
    public void readStringFromContext_LocalizedString() {
        // Given a mocked Context injected into the object under test...
        when(mMockContext.getString(R.string.app_name)).thenReturn(FAKE_STRING);
        ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);

        // ...when the string is returned from the object under test...
        String result = myObjectUnderTest.getHelloWorldString();

        // ...then the result should be the expected one.
        assertThat(result, is(FAKE_STRING));
    }
}

我发现,如果我从app.iml文件中删除行
unitTest with mock works and assembly task,问题是AndroidStudio显示错误,因为无法解析符号。 这也不允许模拟隐藏方法

从命令行执行单元测试 当AndroiStudio执行unitTest时,命令为:

/Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/bin/java -ea -Didea.launcher.port=7537 "-Didea.launcher.bin.path=/Applications/Android Studio.app/Contents/bin" -Didea.junit.sm_runner -Dfile.encoding=UTF-8 -classpath "/Applications/Android Studio.app/Contents/lib/idea_rt.jar: ... :.../app/libs/android-full-23-nexus5x.jar: ... :.../build/generated/mockable-android-23.jar" com.intellij.rt.execution.application.AppMain com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 com.caseonit.pruebamockito.MockUnitTest,readStringFromContext_LocalizedString
AndroidStudio的结果是相同的错误,但是如果我更改classpath参数并在**mockable-android-23.jar*之后设置android-full-23-nexus5x.jar,结果是正确的

所以,我的问题是:是否可以为unitTest更改类路径?我试过了

android.unitTestVariants.all { variant ->
    variant.javaCompile.classpath.minus(['/.../app/libs/android-full-23-nexus5x.jar'])
}
或者类似的,但都不起作用。 你有什么想法或建议吗? 非常感谢你。 致以最良好的祝愿

/Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/bin/java -ea -Didea.launcher.port=7537 "-Didea.launcher.bin.path=/Applications/Android Studio.app/Contents/bin" -Didea.junit.sm_runner -Dfile.encoding=UTF-8 -classpath "/Applications/Android Studio.app/Contents/lib/idea_rt.jar: ... :.../app/libs/android-full-23-nexus5x.jar: ... :.../build/generated/mockable-android-23.jar" com.intellij.rt.execution.application.AppMain com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 com.caseonit.pruebamockito.MockUnitTest,readStringFromContext_LocalizedString
android.unitTestVariants.all { variant ->
    variant.javaCompile.classpath.minus(['/.../app/libs/android-full-23-nexus5x.jar'])
}