[英]Getting ClassNotFoundException when running Robolectric tests with the Maven surefire plugin
I've set up a project in Eclipse using the Android Maven integration, and Robolectric for some tests.我已经使用 Android Maven 集成在 Eclipse 中设置了一个项目,并使用 Robolectric 进行了一些测试。
The tests run fine when I deploy them in Eclipse.当我将它们部署在 Eclipse 中时,测试运行良好。 However, when I try to build the project with the Maven "install" goal (this is actually a library that I need in my local Maven repository), it fails on these same tests.
但是,当我尝试使用Maven“安装”目标(这实际上是我在本地 Maven 存储库中需要的库)构建项目时,它在这些相同的测试中失败。
Logs show the following error:日志显示以下错误:
testAll((package).MyTest) Time elapsed: 0.006 sec <<< ERROR!
java.lang.RuntimeException: java.lang.ClassNotFoundException: caught an exception while obtaining a class file for (package).R
at com.xtremelabs.robolectric.RobolectricTestRunner.createResourceLoader(RobolectricTestRunner.java:316)
at com.xtremelabs.robolectric.RobolectricTestRunner.setupApplicationState(RobolectricTestRunner.java:270)
at com.xtremelabs.robolectric.RobolectricTestRunner.internalBeforeTest(RobolectricTestRunner.java:221)
at com.xtremelabs.robolectric.RobolectricTestRunner.methodBlock(RobolectricTestRunner.java:201)
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.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)
Caused by: java.lang.ClassNotFoundException: caught an exception while obtaining a class file for (package).R
at javassist.Loader.findClass(Loader.java:359)
at com.xtremelabs.robolectric.bytecode.RobolectricClassLoader.findClass(RobolectricClassLoader.java:60)
at javassist.Loader.loadClass(Loader.java:311)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at com.xtremelabs.robolectric.bytecode.RobolectricClassLoader.loadClass(RobolectricClassLoader.java:37)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at com.xtremelabs.robolectric.RobolectricTestRunner.createResourceLoader(RobolectricTestRunner.java:312)
... 22 more
Caused by: com.xtremelabs.robolectric.bytecode.IgnorableClassNotFoundException: msg because of javassist.NotFoundException: (package).R
at com.xtremelabs.robolectric.bytecode.AndroidTranslator.onLoad(AndroidTranslator.java:80)
at javassist.Loader.findClass(Loader.java:340)
... 29 more
where (package) is of course the name of my main package.其中(包)当然是我的主要 package 的名称。 Here's the relevant section of my POM:
这是我的 POM 的相关部分:
<dependencies>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<version>2.1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.pivotallabs</groupId>
<artifactId>robolectric</artifactId>
<version>0.9.8</version>
<type>jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>maven-android-plugin</artifactId>
<version>2.8.3</version>
<configuration>
<genDirectory>${project.basedir}/gen</genDirectory>
<androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile>
<assetsDirectory>${project.basedir}/assets</assetsDirectory>
<resourceDirectory>${project.basedir}/res</resourceDirectory>
<nativeLibrariesDirectory>${project.basedir}/src/main/native</nativeLibrariesDirectory>
<sdk>
<platform>7</platform>
</sdk>
<deleteConflictingFiles>true</deleteConflictingFiles>
<undeployBeforeDeploy>true</undeployBeforeDeploy>
</configuration>
<extensions>true</extensions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<excludes>
<exclude>**/Test*.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
</plugin>
</plugins>
</build>
As you can see, I've tried adding the "genDirectory" option to the Maven Android plugin.如您所见,我尝试将“genDirectory”选项添加到 Maven Android 插件中。 But to no avail.
但无济于事。
What am I missing to make the surefire plugin "see" the R class?为了让surefire插件“看到” R class,我缺少什么?
One more thing: the R class is not actually referenced by my code.还有一件事:我的代码实际上并未引用 R class 。
I also got exactly this issue.我也得到了这个问题。
So I compared carefully between RobolectricSample project and my project.所以我仔细比较了 RobolectricSample 项目和我的项目。
To my surprise, the RobolectricSample project also could NOT work if I didn't run the command line of "mvn clean test" first.令我惊讶的是,如果我没有先运行“mvn clean test”命令行,RobolectricSample 项目也无法运行。
Therefore I analysed the difference and found that the command line compiled the "gen/xxx/R.java" to "target/classes/xxx/R" too.因此我分析了差异,发现命令行也将“gen/xxx/R.java”编译为“target/classes/xxx/R”。
That's the trick of success so I did the following steps: 1. right click project -> Java Build;这就是成功的诀窍,所以我做了以下步骤:1.右键单击项目-> Java Build; 2. change the "{project}/gen" output folder as "target/class" (instead of original "target/android-classes")
2.将“{project}/gen”output文件夹更改为“target/class”(而不是原来的“target/android-classes”)
That's it and hope this helps.就是这样,希望这会有所帮助。
I found that the only way to fix this issue was to place a fake R.java file into the package:我发现解决此问题的唯一方法是将伪造的 R.java 文件放入 package 文件中:
public class R {
public static final class attr {
}
public static final class drawable {
}
public static final class id {
}
public static final class layout {
}
public static final class string {
}
}
This should only be necessary under the following circumstances:只有在以下情况下才需要这样做:
Note: You can put R.java in your test sources so that it isn't deployed.注意:您可以将 R.java 放在您的测试源中,这样它就不会被部署。 This won't then interfere with actual resources created.
这不会干扰创建的实际资源。
I've had the same problem when trying to run a test from Eclipse, first time after adding Robolectric.在添加 Robolectric 后第一次尝试从 Eclipse 运行测试时,我遇到了同样的问题。
What solved the problem for me was mvn clean test
on the command line.为我解决问题的是命令行上的
mvn clean test
。 After that, the test ran OK from Eclipse as well.之后,测试也从 Eclipse 运行正常。
And make sure you have <packaging>apk</packaging>
in your pom.xml.并确保您的 pom.xml 中有
<packaging>apk</packaging>
。
I had this same issue when running Robolectric tests both in eclipse and on the command line via mvn clean test
.在 eclipse 和命令行上通过
mvn clean test
运行 Robolectric 测试时,我遇到了同样的问题。 Ie a java.lang.ClassNotFoundException
complaining that my R.class file was not found.即一个
java.lang.ClassNotFoundException
抱怨我的 R.class 文件没有找到。 Indeed, there was no R.class file since my project is an Android library that has no resources.实际上,没有 R.class 文件,因为我的项目是一个没有资源的 Android 库。
A dirty hack to get rid of the error is to create a <project-home>/res/values/strings.xml
file with a single unused string.摆脱错误的肮脏技巧是使用单个未使用的字符串创建
<project-home>/res/values/strings.xml
文件。 Then the R.java and the corresponding R.class are generated and the error goes away.然后 R.java 和相应的 R.ZA2F2ED4F8EBC2CBB14C21A29DC 生成的错误消失了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.