Getting a ClassNotFoundException when running Robolectric tests with the Maven surefire plugin

I created a project in Eclipse using Android Maven integration, and Robolectric for some tests.

Tests run fine when I deploy them to Eclipse. However, when I try to build a project using Maven to “set” the goal (this is actually the library that I need in my local Maven repository), it fails in the same tests.

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. Here is the relevant section of my 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 tried to add the "genDirectory" parameter to the Maven Android plugin. But to no avail.

What am I missing to make the surefire plugin "see" the R class?

One more thing: the class R does not actually reference my code.

+4
android maven robolectric
source share
4 answers

I had the same problem when trying to run a test from Eclipse, for the first time after adding Robolectric.

What solved the problem for me was mvn clean test on the command line. After that, the test also went fine with Eclipse.

And make sure you have <packaging>apk</packaging> in your pom.xml.

+3
source share

I also got exactly this problem.

Therefore, I carefully compared the RobolectricSample project and my project.

To my surprise, the RobolectricSample project CANNOT work either if I didn’t run the “mvn clean test” command line at first.

So I analyzed the difference and found that the command line compiled "gen / xxx / R.java" into "target / classes / xxx / R".

This is a success trick, so I took the following steps: 1. right-click project → Java Build; 2. change the output folder "{project} / gen" to "target / class" (instead of the original "target / android classes")

This is hoping this helps.

+4
source share

I found that the only way to fix this problem is to put a fake R.java file in the 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 is only necessary in the following circumstances:

  • Maven Library Project
  • unit test dependent on Robolectric
  • R.java is not created or not found on the path to the maven class.

Note. You can put R.java in your test sources so that it is not deployed. This will not interfere with the actual resources created.

+4
source share

I had the same problem when running Robolectric tests in both eclipse and command line through mvn clean test . That is a java.lang.ClassNotFoundException , complaining that my R.class file was not found. Indeed, there was no R.class file, since my project is an Android library that has no resources.

A dirty hack to get rid of the error is to create a <project-home>/res/values/strings.xml with one unused line. Then R.java and the corresponding R.class are generated, and the error disappears.

0
source share

All Articles