簡體   English   中英

使用 Maven surefire 插件運行 Robolectric 測試時出現 ClassNotFoundException

[英]Getting ClassNotFoundException when running Robolectric tests with the Maven surefire plugin

我已經使用 Android Maven 集成在 Eclipse 中設置了一個項目,並使用 Robolectric 進行了一些測試。

當我將它們部署在 Eclipse 中時,測試運行良好。 但是,當我嘗試使用Maven“安裝”目標(這實際上是我在本地 Maven 存儲庫中需要的庫)構建項目時,它在這些相同的測試中失敗。

日志顯示以下錯誤:

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

其中(包)當然是我的主要 package 的名稱。 這是我的 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>

如您所見,我嘗試將“genDirectory”選項添加到 Maven Android 插件中。 但無濟於事。

為了讓surefire插件“看到” R class,我缺少什么?

還有一件事:我的代碼實際上並未引用 R class 。

我也得到了這個問題。

所以我仔細比較了 RobolectricSample 項目和我的項目。

令我驚訝的是,如果我沒有先運行“mvn clean test”命令行,RobolectricSample 項目也無法運行。

因此我分析了差異,發現命令行也將“gen/xxx/R.java”編譯為“target/classes/xxx/R”。

這就是成功的訣竅,所以我做了以下步驟:1.右鍵單擊項目-> Java Build; 2.將“{project}/gen”output文件夾更改為“target/class”(而不是原來的“target/android-classes”)

就是這樣,希望這會有所幫助。

我發現解決此問題的唯一方法是將偽造的 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 {
        }
    }

只有在以下情況下才需要這樣做:

  1. Maven庫項目
  2. 對 Robolectric 的單元測試依賴
  3. R.java 未生成或未在 maven 類路徑上找到。

注意:您可以將 R.java 放在您的測試源中,這樣它就不會被部署。 這不會干擾創建的實際資源。

在添加 Robolectric 后第一次嘗試從 Eclipse 運行測試時,我遇到了同樣的問題。

為我解決問題的是命令行上的mvn clean test 之后,測試也從 Eclipse 運行正常。

並確保您的 pom.xml 中有<packaging>apk</packaging>

在 eclipse 和命令行上通過mvn clean test運行 Robolectric 測試時,我遇到了同樣的問題。 即一個java.lang.ClassNotFoundException抱怨我的 R.class 文件沒有找到。 實際上,沒有 R.class 文件,因為我的項目是一個沒有資源的 Android 庫。

擺脫錯誤的骯臟技巧是使用單個未使用的字符串創建<project-home>/res/values/strings.xml文件。 然后 R.java 和相應的 R.ZA2F2ED4F8EBC2CBB14C21A29DC 生成的錯誤消失了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM