【问题标题】:Robolectric Unit Test failing with Android Studio 2.3 updatesRobolectric 单元测试因 Android Studio 2.3 更新而失败
【发布时间】:2017-03-13 23:31:45
【问题描述】:

我所有的单元测试都开始抛出这个错误:

No such manifest file: build\intermediates\bundles\debug\AndroidManifest.xml

java.lang.NullPointerException
    at org.robolectric.shadows.ShadowAssetManager.getAndResolve(ShadowAssetManager.java:375)
    at org.robolectric.shadows.ShadowAssetManager.getResourceValue(ShadowAssetManager.java:117)
    at android.content.res.AssetManager.getResourceValue(AssetManager.java)
    at android.content.res.Resources.getValue(Resources.java:1347)
    at android.support.v7.widget.AppCompatDrawableManager.loadDrawableFromDelegates(AppCompatDrawableManager.java:332)
    at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:197)
    at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:190)
    at android.support.v7.widget.AppCompatDrawableManager.checkVectorDrawableSetup(AppCompatDrawableManager.java:711)
    at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:195)
    at android.support.v7.widget.TintTypedArray.getDrawableIfKnown(TintTypedArray.java:81)
    at android.support.v7.app.AppCompatDelegateImplBase.__constructor__(AppCompatDelegateImplBase.java:131)
    at android.support.v7.app.AppCompatDelegateImplBase.<init>(AppCompatDelegateImplBase.java)
    at android.support.v7.app.AppCompatDelegateImplV9.<init>(AppCompatDelegateImplV9.java)
    at android.support.v7.app.AppCompatDelegateImplV11.<init>(AppCompatDelegateImplV11.java)
    at android.support.v7.app.AppCompatDelegateImplV14.<init>(AppCompatDelegateImplV14.java)
    at android.support.v7.app.AppCompatDelegateImplV23.<init>(AppCompatDelegateImplV23.java)
    at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:203)
    at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:185)
    at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:519)
    at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:71)
    at android.app.Activity.performCreate(Activity.java:6237)
    at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:195)
    at org.robolectric.util.ActivityController$1.run(ActivityController.java:126)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:340)
    at org.robolectric.shadows.CoreShadowsAdapter$2.runPaused(CoreShadowsAdapter.java:40)
    at org.robolectric.util.ActivityController.create(ActivityController.java:123)
    at org.robolectric.util.ActivityController.create(ActivityController.java:133)
    at com.si.play.adapter.RosterAdapter2Test.setUp(RosterAdapter2Test.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:250)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:176)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:142)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)

它工作得很好。我唯一改变的是我将 Android Studio 更新到 2.3 并将 gradle 插件更新到 2.3。到目前为止,我通过在每个测试的运行配置路径中手动写下$MODULE_DIR$ 来修复它。但是每次都写下来真的很烦。有没有人经历过这样的事情?

【问题讨论】:

    标签: android unit-testing android-studio robolectric


    【解决方案1】:

    默认设置,因此您创建的每个新测试配置都会继承它:

    运行 > 编辑配置... > 默认值 > Android JUnit

    工作目录输入:$MODULE_DIR$

    【讨论】:

    • 这里要记住的另一件事是,如果您在设置 Working directory 后尝试重新运行先前失败的测试,它可能仍然会失败,因为它可能已经存在没有 Working directory 的配置(在列表中的较高位置)窗口)。请务必删除以前的 JUnit 配置!
    【解决方案2】:

    当有人遇到这个问题时,对于这种情况,添加这一行应该会有所帮助

    在“android”括号中

    在 app/build.gradle 中

    testOptions.unitTests {
        includeAndroidResources = true
    }
    

    【讨论】:

      【解决方案3】:

      Android Studio 正在查看 APP 文件夹以从 AS 2.3 版本运行测试。如果您有自定义 Roboelectric Runner 扩展 RoboelectricTestRunner,您可以覆盖其中的工作目录,而不是每次都从编辑配置中设置 WORKING DIR。

      这是我的代码。

      public class CustomRobolectricRunner extends RobolectricTestRunner {
      
          // Build output location for Android Studio 2.2 and older
          private static final String BUILD_OUTPUT = "build/intermediates";
      
          // Build output location for Android Studio 2.3 and newer
          private static final String BUILD_OUTPUT_APP_LEVEL = "app/build/intermediates";
      
          public CustomRobolectricRunner(Class<?> testClass) throws InitializationError {
              super(testClass);
          }
      
          @Override
          protected AndroidManifest getAppManifest(Config config) {
              FileFsFile res = FileFsFile.from(BUILD_OUTPUT, "/res/merged", BuildConfig.FLAVOR, BuildConfig.BUILD_TYPE);
              FileFsFile assets = FileFsFile.from(BUILD_OUTPUT, "assets", BuildConfig.FLAVOR, BuildConfig.BUILD_TYPE);
              FileFsFile manifest = FileFsFile.from(BUILD_OUTPUT, "manifests", "full", BuildConfig.FLAVOR, BuildConfig.BUILD_TYPE, "AndroidManifest.xml");
      
              // If above files does not exist in the specified paths, look them at the app folder level. This is needed
              // as Android studio 2.3 changed the working directory.
              if (!manifest.exists()) {
                  manifest = FileFsFile.from(BUILD_OUTPUT_APP_LEVEL, "manifests", "full", BuildConfig.FLAVOR, BuildConfig.BUILD_TYPE, "AndroidManifest.xml");
              }
      
              if (!res.exists()) {
                  res = FileFsFile.from(BUILD_OUTPUT_APP_LEVEL, "/res/merged", BuildConfig.FLAVOR, BuildConfig.BUILD_TYPE);
              }
      
              if (!assets.exists()) {
                  assets = FileFsFile.from(BUILD_OUTPUT_APP_LEVEL, "assets", BuildConfig.FLAVOR, BuildConfig.BUILD_TYPE);
              }
      
              AndroidManifest androidManifest = new AndroidManifest(manifest, res, assets) {
                  @Override
                  public Class getRClass() {
                      return R.class;
                  }
      
                  public int getTargetSdkVersion() {
                      /**
                       * Lollipop is currently the highest version supported in 3.0.
                       */
                      return Build.VERSION_CODES.LOLLIPOP;
                  }
              };
      
              return androidManifest;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-06
        • 2015-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多