1

我有一个在 Eclipse 中配置了 maven 的带有 Google Maps V2 的 Android 应用程序。所以我在 worspace 中有一个“mavenized”的 Google Play Services 库,并且应用程序 pom 对 google-play-services jar 和 apklib 有两个 maven 依赖项。

我实现了一个虚拟测试,它只检查地图片段是否不为空:

@RunWith(RobolectricTestRunner.class)
public class MapsTest {

    private GoogleMap map;
    private ElementMapActivity activity;

    @Before
    public void setUp() throws Exception {
        activity = new ElementMapActivity();
        activity.onCreate(null);
    }

    @Test
    public void mapExists() {
        // Try to obtain the map from the SupportMapFragment.
        map = ((SupportMapFragment) activity.getSupportFragmentManager()
                .findFragmentById(R.id.elementMap)).getMap();
        Assert.assertNotNull(map);
    }   
}

注意:在实际的应用程序活动中使用了类似的代码来显示地图,并且运行正常。

我没有实现任何自定义测试运行器。

我用 maven 运行测试:mvn test。

使用 Robolectric 1.2,测试构建并执行,但 assertNotNull 失败,因为地图实例为空。片段未正确恢复。

使用 Robolectric 2.1.1 测试构建但无法执行。我为项目中的每个测试都得到了一个例外(不仅是测试地图的那个):

WARNING: no system properties value for ro.build.date.utc
java.lang.RuntimeException: .\..\google-play-services_lib\AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
    at org.robolectric.AndroidManifest.validate(AndroidManifest.java:108)
    at org.robolectric.AndroidManifest.getResourcePath(AndroidManifest.java:274)
    at org.robolectric.AndroidManifest.getIncludedResourcePaths(AndroidManifest.java:280)
    at org.robolectric.AndroidManifest.getIncludedResourcePaths(AndroidManifest.java:282)
    at org.robolectric.RobolectricTestRunner.createAppResourceLoader(RobolectricTestRunner.java:576)
    at org.robolectric.RobolectricTestRunner.getAppResourceLoader(RobolectricTestRunner.java:568)
    at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:89)
    at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:387)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:227)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:177)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:59)
    at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:120)
    at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:103)
    at org.apache.maven.surefire.Surefire.run(Surefire.java:169)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:350)
    at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021)

似乎 Robolectric 尝试使用 google-play-services 库清单而不是主应用程序清单,该清单位于默认位置:应用程序根文件夹。库清单也在它自己的根文件夹中。

我是否缺少一些测试配置?我应该使用自定义测试运行器吗?还是 Robolectric 2 不支持 Google Maps V2?

编辑:我可以不用地图测试。问题是,对于 Robolectric 2,所有其他测试也会出现此错误,只是通过具有 google-play-library 依赖项,所以我现在不能使用 Robolectric 2。我想知道这是否是一个已知错误,以便决定是否返回 Robolectric 1。我检查了 Robolectric 错误报告并没有找到任何关于此的内容。

4

2 回答 2

0

我最近在我的 Maven 构建计划下运行 Robolectric 测试时遇到了与 ActionBarSherlock 相同的问题。

当我在 Windows 机器上完成构建时,问题并不明显,直到我将笔记本电脑换成 OSX 电源设备后才变得明显。

我发现问题在于库名称“google-play-services_lib”与目录结构中的文件夹名称不(完全)匹配。在我的例子中,我的 Eclipse 项目被称为“ActionBarSherlock-4.3.1”,而文件夹本身在文件系统下被称为“actionbarsherlock”。

我建议您同步这两个名称(Eclipse 项目和文件系统)并重新运行您的测试。希望有帮助。

于 2013-07-25T08:14:09.230 回答
0

使用 Robolectric 2.1.1 测试使用 google-play-services_lib (Google Maps) 的 Android 应用程序会产生 AndroidManifest.xml not found RuntimeException。

简短的答案在这里以粗体显示。长答案在它下面。

在您的项目中查找名为 project.properties 的文件

创建一个名为 test-project.properties 的新文件

覆盖任何或所有 android.library.reference.$

例如在我的 project.properties 它有这个库参考:

**android.library.reference.1=../../../ADK/adt-bundle-windows-x86_64-20130522/sdk/extras/google/google_play_services/libproject/google-play-services_lib**

我在 test-project.properties 文件中覆盖了它

android.library.reference.1=res

将 google-play-services_lib 中的 AndroidManifest.xml 放入您正在测试的项目的 res(或项目中的任何文件夹)文件夹中

长答案:

我遇到了同样的问题,并认为问题与上述“google-play-services library manifest 而不是 main application manifest”相同,所以我删除了对 google-place-services_lib 的所有引用,但仍然收到错误. 我从 github 下载了 2.1.1 Robolectric 代码并开始通过它进行调试。我发现 org.robolectric.AndroidManifest 类有一个名为 getLibraryManifests 的方法,它调用 createLibraryManifests 并调用 findLibraries。它所做的其中一件事是在您的项目中加载 project.properties 文件。在我的情况下,我的 project.properties 文件的内容为:
android.library.reference.1=../../../ADK/adt-bundle-windows-x86_64-20130522/sdk/extras/google/google_play_services/libproject /google-play-services_lib

这是在我使用 Android 工具来根据 Google 的文档安装 google play 服务时创建的。如果您从 project.properties 文件中注释掉该行,那么错误就会消失。更好的解决方案是保留它,然后创建自己的名为 test-project.properties 的文件,并将其放入 android.library.reference.1 的正确目录中,AndroidManifest 将覆盖原始值。

这是来自 AndroidManifest.java 的相关代码

protected List<FsFile> findLibraries() {
FsFile baseDir = getBaseDir();
List<FsFile> libraryBaseDirs = new ArrayList<FsFile>();

Properties properties = getProperties(baseDir.join("project.properties"));
// get the project.properties overrides and apply them (if any)
Properties overrideProperties = getProperties(baseDir.join("test-project.properties"));
if (overrideProperties!=null) properties.putAll(overrideProperties);
if (properties != null) {
int libRef = 1;
String lib;
while ((lib = properties.getProperty("android.library.reference." + libRef)) != null) {
FsFile libraryBaseDir = baseDir.join(lib);
libraryBaseDirs.add(libraryBaseDir);
libRef++;
}
}
return libraryBaseDirs;
}
于 2013-09-17T19:11:28.500 回答