简体   繁体   English

使用 Maven surefire 插件运行 Robolectric 测试时出现 ClassNotFoundException

[英]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:只有在以下情况下才需要这样做:

  1. Maven library project Maven库项目
  2. unit test dependencies on Robolectric对 Robolectric 的单元测试依赖
  3. R.java not being generated or not found on maven classpath. R.java 未生成或未在 maven 类路径上找到。

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.

相关问题 通过robolectric插件运行android单元测试 - Running android unit tests via robolectric plugin 获取java.lang.RuntimeException:通过Maven运行Robolectric时存根 - Getting java.lang.RuntimeException: Stub when running Robolectric through Maven 在Android Studio中运行Robolectric测试时如何调试? - How to debug when running Robolectric tests in Android Studio? Android单元测试-使用Robolectric运行MockServer时出现IncompatibleClassChangeError - Android unit tests - IncompatibleClassChangeError when running MockServer with Robolectric 使用Robolectric运行JUnit测试时出现Gradle和Android Studio问题 - Gradle and Android Studio issue when running JUnit tests using Robolectric 运行Robolectric测试时是否发送Firebase分析事件? - Are Firebase analytics events sent when running Robolectric tests? Robolectric:运行多个测试失败 - Robolectric: running multiple tests fails 运行Robolectric单元测试失败 - Running Robolectric unit tests fails robolectric的Maven依赖范围要么停止运行测试,要么使构建耗尽堆空间 - Maven dependency scope for robolectric either stops tests running or makes build run out of heap space Robolectric测试抛出RuntimeException:java.lang.ClassNotFoundException - Robolectric tests throw RuntimeException: java.lang.ClassNotFoundException
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM