【问题标题】:Robolectric can't find resource or manifest fileRobolectric 找不到资源或清单文件
【发布时间】:2013-09-10 10:04:57
【问题描述】:

我创建了一个新的 TestProject 并在我的 testMethod 中添加了以下行:

Robolectric.getShadowApplication().getString(R.string.mystring);

我的测试失败了

android.content.res.Resources$NotFoundException: unknown resource 2131558482

控制台显示以下警告:

WARNING: No manifest file found at .\..\..\MyProject\AndroidManifest.xml.Falling back to the Android OS resources only.
To remove this warning, annotate your test class with @Config(manifest=Config.NONE).
WARNING: no system properties value for ro.build.date.utc

AndroidManifest.xml 是否需要获取字符串资源? 我尝试通过 org.robolectric.Config.properties@Config 添加 Manifest,但警告仍然出现,我无法获取字符串资源。我确保清单的相对路径是正确的。 我还尝试更改 JUnit 运行配置,但这没有帮助。

【问题讨论】:

    标签: android android-manifest robolectric


    【解决方案1】:

    这里描述的问题的解决方案: http://blog.futurice.com/android_unit_testing_in_ides_and_ci_environments

    失踪的清单

    您现在应该已经注意到 Robolectric 抱怨无法找到您的 Android Manifest。我们将通过编写自定义测试运行器来解决这个问题。将以下内容添加为 app/src/test/java/com/example/app/test/RobolectricGradleTestRunner.java:

    package com.example.app.test;
    
    import org.junit.runners.model.InitializationError;
    import org.robolectric.manifest.AndroidManifest;
    import org.robolectric.RobolectricTestRunner;
    import org.robolectric.annotation.Config;
    import org.robolectric.res.Fs;
    
    public class RobolectricGradleTestRunner extends RobolectricTestRunner {
      public RobolectricGradleTestRunner(Class<?> testClass) throws InitializationError {
        super(testClass);
      }
    
      @Override
      protected AndroidManifest getAppManifest(Config config) {
        String myAppPath = RobolectricGradleTestRunner.class.getProtectionDomain()
                                                            .getCodeSource()
                                                            .getLocation()
                                                            .getPath();
        String manifestPath = myAppPath + "../../../src/main/AndroidManifest.xml";
        String resPath = myAppPath + "../../../src/main/res";
        String assetPath = myAppPath + "../../../src/main/assets";
        return createAppManifest(Fs.fileFromPath(manifestPath), Fs.fileFromPath(resPath), Fs.fileFromPath(assetPath));
      }
    }
    

    记得更改测试类中的 RunWith 注解。

    【讨论】:

    • 不错的解决方案,但这不适用于 Android Studio 1.1。自从支持单元测试以来,路径可能已经改变。这些路径对我有用:String manifestPath = myAppPath + "../../../manifests/full/debug/AndroidManifest.xml"; String resPath = myAppPath + "../../../res/debug"; String assetPath = myAppPath + "../../../assets/debug";
    • 我真的不明白,为什么 createAppManifest(...) 方法无法解析?缺少什么?
    • 未来链接坏了
    【解决方案2】:

    我也遇到了同样的错误,我们使用了几种风格和构建类型所以,有一些步骤可以让它工作:

    1) Android studio 测试运行配置

    您也必须在 Windows 中将工作目录设置为 $MODULE_DIR$。 http://robolectric.org/getting-started/ 应该这么说。

    2) 单元测试应该这样注释:

    @RunWith(RobolectricTestRunner.class) 
    @Config(constants = BuildConfig.class, sdk = 21, manifest = "src/main/AndroidManifest.xml", packageName = "com.example.yourproject") 
    public class SomeFragmentTest {
    

    这里我们有指向清单文件和包名的简单链接

    【讨论】:

      【解决方案3】:

      从 4.0 版本开始,@Config 的使用并不受欢迎,但是更新的入门指南解决了我的问题:http://robolectric.org/getting-started/

      只需修改一次build.gradle,加载Manifest文件,即可运行测试。

      android {
        testOptions {
          unitTests {
            includeAndroidResources = true
          }
        }
      }
      

      github上的相关issue(也已关闭):https://github.com/robolectric/robolectric/issues/3328

      【讨论】:

      • 您还必须添加@Config(sdk = [Build.VERSION_CODES.O_MR1]) 否则会报错Failed to create a Robolectric sandbox
      【解决方案4】:

      您需要一个AndroidManifest.xml,而 Robolectric 目前依赖于它位于项目根目录中,如路径所示。

      【讨论】:

        【解决方案5】:

        我注意到我曾经在我的测试类的顶部这样声明清单

        @RunWith(RobolectricTestRunner.class)
        @Config( constants = BuildConfig.class, manifest="app/src/main/AndroidManifest.xml", sdk = 21 )
        

        为了工作,我现在切换到这个。

        @RunWith(RobolectricTestRunner.class)
        @Config( constants = BuildConfig.class, manifest="src/main/AndroidManifest.xml", sdk = 21 )
        

        【讨论】:

        • 你知道为什么吗?相同的代码在两台 OS X 机器上运行,一台使用 src/main... 正确构建,第二台使用 app/src/main/...。我不知道为什么会这样
        • 这是由于 JUnit 运行配置中的工作目录不正确,如@Kirill Vashilo 回答中所述
        【解决方案6】:

        我刚刚解决了与 Robolectric 相同的问题(版本:robolectric-2.4-jar-with-dependencies.jar)并返回未知资源,同时从不同的值*文件夹加载资源,例如:

        <resources>
            <string name="screen_type">10-inch-tablet</string>
        </resources>
        

        就我而言,我想识别不同的设备。为此,我在以下文件夹中创建了 screen.xml:

        values/screen.xml - mobile
        values-sw600dp/screen.xml - 7-inch tablet
        values-sw720dp/screen.xml - 10-inch tablet
        

        我的工作区如下:

        workspace
           \-ExProj
               \-exProj
                    \-src
                        \-exProj
                            \-AndroidManifest.xml
           \-ExProjTest
        

        我对 Robolectric 的单元测试:

        @RunWith(RobolectricTestRunner.class)
        @Config(manifest = "./../ExProj/exProj/src/exProj/AndroidManifest.xml")
        public class UtilityTest {
        
          @Test
           @Config(qualifiers = "sw720dp")
            public void testIfDeviceIsTablet() throws Exception {
             System.out.println(Robolectric.application.getString(R.string.screen_type));
            }
        }
        

        上面的测试代码在控制台上打印出来:10-inch-tablet...

        【讨论】:

          【解决方案7】:

          我通过继承 RobolectricTestRunner 来覆盖 getConfigProperties()。请点击此链接:https://stackoverflow.com/a/29907234/727654

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-05-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-05-16
            • 2016-01-03
            相关资源
            最近更新 更多