Java 如何在测试范围内使用m2e(Eclipse/Maven)运行具有测试依赖性的命令行程序?

Java 如何在测试范围内使用m2e(Eclipse/Maven)运行具有测试依赖性的命令行程序?,java,eclipse,maven,testing,m2eclipse,Java,Eclipse,Maven,Testing,M2eclipse,我在运行带有m2e插件的java应用程序(静态void main)时遇到问题。我通过普通的eclipse向导创建了一个多模块项目。似乎一个模块的测试目录中的代码在运行时无法引用另一个模块的测试目录中的代码(编译工作正常) 版本信息 Eclipse=Luna,构建4.4.0,构建id 20140612-0600 m2e=1.5.0.20140606-0033 我创建了一个非常简单(而且是精心设计的)的示例来演示我的问题。请对我宽容一点,因为这段代码毫无意义。还有,请原谅我在这里说得太多了。可悲

我在运行带有m2e插件的java应用程序(静态void main)时遇到问题。我通过普通的eclipse向导创建了一个多模块项目。似乎一个模块的测试目录中的代码在运行时无法引用另一个模块的测试目录中的代码(编译工作正常)

版本信息

  • Eclipse=Luna,构建4.4.0,构建id 20140612-0600
  • m2e=1.5.0.20140606-0033
我创建了一个非常简单(而且是精心设计的)的示例来演示我的问题。请对我宽容一点,因为这段代码毫无意义。还有,请原谅我在这里说得太多了。可悲的是,专业问题几乎需要它


以下是项目目录结构:

--Project Explorer
 |--animals/
   |--src/test/java/
     |--com.example.problem.animals
       |--Animal.java
   |--JRE System Library [JavaSE-1.8]
   |--src/
   |--target/
   |--pom.xml
 |--dogs/
   |--src/test/java/
     |--com.example.problem.animals
       |--Beagle.java
   |--JRE System Library [JavaSE-1.8]
   |--Maven Dependencies
     |--animals/
   |--src/
   |--target/
   |--pom.xml
 |--parent/
   |--animals/
   |--dogs/
   |--src/
   |--pom.xml

父模块pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.problem</groupId>
  <artifactId>parent</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>

  <name>Parent</name>
  <description>Parent module for example project.</description>

  <modules>
    <module>animals</module>
    <module>dogs</module>
  </modules>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.example.problem</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>animals</artifactId>

  <name>Animals</name>
  <description>Module to hold common animal code.</description>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.example.problem</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>dogs</artifactId>

  <name>Dogs</name>
  <description>Module to hold dog specific code.</description>

  <dependencies>
    <dependency>
      <groupId>com.example.problem</groupId>
      <artifactId>animals</artifactId>
      <version>0.0.1-SNAPSHOT</version>
    </dependency>
  </dependencies>
</project>
Beagle.java:

package com.example.problem.animals;

/*
 * Runnable java class that simply prints the animal noise for Beagle to the console.
 *
 * @author Rich - created 03/Sep/2014
 */
@Animal(noise = "Woof!")
public class Beagle {
  public static void main(String[] args) {
    Animal animal = Beagle.class.getAnnotation(Animal.class);
    System.out.println(animal.noise());
  }
}

为了运行Beagle类,我使用eclipse向导创建了一个新的运行配置。配置类型为“Maven Build”。“JRE”选项卡将“运行时JRE”设置为“工作区默认JRE(jre1.8.0_20)”。在配置的“主”选项卡上进行以下设置:

  • “基本目录”字段设置为“${workspace\u loc:/dogs}”
  • “目标”字段设置为“exec:java”
  • “配置文件”字段未设置
  • “用户设置”字段未设置
  • 未选中“脱机”、“更新快照”、“调试输出”、“跳过测试”和“非递归”复选框
  • 已选中“解析工作区工件”复选框
  • 添加的参数
    • “exec.mainClass”设置为“com.example.problem.animals.Beagle”
    • “exec.classpathScope”设置为“test”
  • “Maven运行时”设置为“嵌入式(3.2.1/1.5.0.20140605-2032)”
运行此配置最终失败,并产生以下控制台输出:

[INFO] Scanning for projects...
[INFO] 
[INFO] Using the builder org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder with a thread count of 1
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Dogs 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- exec-maven-plugin:1.3.2:java (default-cli) @ dogs ---
[WARNING] Warning: killAfter is now deprecated. Do you need it ? Please comment on MEXEC-6.
[WARNING] 
java.lang.reflect.InvocationTargetException
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at java.lang.reflect.Method.invoke(Unknown Source)
  at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:293)
  at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NoClassDefFoundError: com/example/problem/animals/Animal
  at com.example.problem.animals.Beagle.main(Beagle.java:6)
  ... 6 more
Caused by: java.lang.ClassNotFoundException: com.example.problem.animals.Animal
  at java.net.URLClassLoader$1.run(Unknown Source)
  at java.net.URLClassLoader$1.run(Unknown Source)
  at java.security.AccessController.doPrivileged(Native Method)
  at java.net.URLClassLoader.findClass(Unknown Source)
  at java.lang.ClassLoader.loadClass(Unknown Source)
  at java.lang.ClassLoader.loadClass(Unknown Source)
  ... 7 more
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.282 s
[INFO] Finished at: 2014-09-13T18:25:51-08:00
[INFO] Final Memory: 9M/155M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.3.2:java (default-cli) on project dogs: An exception occured while executing the Java class. null: InvocationTargetException: com/example/problem/animals/Animal: com.example.problem.animals.Animal -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
在运行设置了“Debug Output”的配置之后,我在控制台中找到了以下有趣的行:

[DEBUG] Configuring mojo 'org.codehaus.mojo:exec-maven-plugin:1.3.2:java' with basic configurator -->
[DEBUG]   (f) arguments = []
[DEBUG]   (f) classpathScope = test
[DEBUG]   (f) cleanupDaemonThreads = true
[DEBUG]   (f) daemonThreadJoinTimeout = 15000
[DEBUG]   (f) includePluginDependencies = false
[DEBUG]   (f) includeProjectDependencies = true
[DEBUG]   (f) keepAlive = false
[DEBUG]   (f) killAfter = 1
[DEBUG]   (f) localRepository =        id: local
...
[DEBUG] Project Dependencies will be included.
[DEBUG] Collected project artifacts [com.example.problem:animals:jar:0.0.1-SNAPSHOT:compile]
[DEBUG] Collected project classpath [C:\Users\cairnsjr13\workspace\parent\dogs\target\test-classes, C:\Users\cairnsjr13\workspace\parent\dogs\target\classes]
[DEBUG] Adding to classpath : file:/C:/Users/cairnsjr13/workspace/parent/dogs/target/test-classes/
[DEBUG] Adding to classpath : file:/C:/Users/cairnsjr13/workspace/parent/dogs/target/classes/
[DEBUG] Adding project dependency artifact: animals to classpath


我之所以如此困惑,是因为它似乎试图包含“动物”依赖。我怀疑它包括主依赖项,而不是测试依赖项。所以在这个冗长的信息转储之后。。。有人知道如何让eclipse(m2e)执行这种情况吗?我已将其正确配置为处理测试编译依赖项,但在我的一生中无法使运行时依赖项正常工作。

exec.classpathScope
设置为
test
将已执行模块的测试类添加到类路径,而不是依赖项的测试类。如调试输出所示,它添加了
模块的测试类,但没有添加
动物
的测试类:

[DEBUG] Adding to classpath : file:/C:/Users/cairnsjr13/workspace/parent/dogs/target/test-classes/
为了依赖于
动物的测试类
,您需要通过指定
测试jar
目标为其配置
maven jar插件
,如中所述

动物

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>test-jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
<dependencies>
    <dependency>
        <groupId>com.example.problem</groupId>
        <artifactId>animals</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <type>test-jar</type> 
        <scope>test</scope>
    </dependency>
</dependencies>
添加此配置后,
动物
模块安装到本地Maven存储库中。这将在本地repo中创建一个Jar,其中包含模块的测试类,特别是
Animal
类,以及为主要类创建的普通Jar。您可以从命令行执行安装,也可以右键单击
animals
项目,然后选择runas->Maven install

然后在Eclipse中启动相同的运行配置,但不选中“解析工作区工件”复选框,以便从本地Maven存储库解析测试工件


在重现您的场景时,我注意到一件奇怪的事情,那就是如果我添加了上述所有Maven配置(Maven jar插件和测试范围的依赖项),但我勾选了“解析工作区工件”复选框,
m2eclipse
无法解析工作区中的测试Jar,即使目标文件夹包含Jar并且项目已刷新/更新。我觉得这是插件本身的一个缺陷,特别是在解决使用
测试Jar
目标配置的工作区测试Jar依赖关系时。

经过大量的增量更改和反复尝试,我已经找到了如何让它工作的方法。这种方法的好处在于,您仍然可以在animals项目中进行积极的开发,而无需每次都将其导出为测试jar。标记具有必须设置的类型属性。然后,dogs pom.xml文件变为:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.example.problem</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>dogs</artifactId>

  <name>Dogs</name>
  <description>Module to hold dog specific code.</description>

  <dependencies>
    <dependency>
      <groupId>com.example.problem</groupId>
      <artifactId>animals</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>test-jar</type>
    </dependency>
  </dependencies>
</project>
这里有几件事需要注意

不需要将scope属性设置为test,即可运行此功能。将测试标记添加到依赖项将导致在非测试范围中忽略该依赖项。因为我们在测试范围内运行,所以这并不重要

这种方法不包括对来自动物的主代码的依赖。在原始问题的示例中,这并不重要,因为没有主代码源目录。如果动物中的测试代码依赖于动物中的主代码,则必须在狗中添加一个额外的依赖项来获取该代码。以下是dogs pom.xml文件在这种情况下的外观:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.example.problem</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>dogs</artifactId>

  <name>Dogs</name>
  <description>Module to hold dog specific code.</description>

  <dependencies>
    <!-- Including both dependencies for jar and test-jar to get main src included. -->
    <dependency>
      <groupId>com.example.problem</groupId>
      <artifactId>animals</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>com.example.problem</groupId>
      <artifactId>animals</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>test-jar</type>
    </dependency>
  </dependencies>
</project>

4.0.0
com.example.problem
父母亲
0.0.1-快照
狗
狗
模块用于保存狗的特定代码。
com.example.problem
动物
0.0.1-快照
罐子
com.example.problem
动物
0.0.1-快照
试验罐
[INFO] Scanning for projects...
[INFO] 
[INFO] Using the builder org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder with a thread count of 1
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Dogs 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- exec-maven-plugin:1.3.2:java (default-cli) @ dogs ---
[WARNING] Warning: killAfter is now deprecated. Do you need it ? Please comment on MEXEC-6.
Woof!
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.310 s
[INFO] Finished at: 2014-09-21T13:53:21-08:00
[INFO] Final Memory: 9M/155M
[INFO] ------------------------------------------------------------------------
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.example.problem</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>dogs</artifactId>

  <name>Dogs</name>
  <description>Module to hold dog specific code.</description>

  <dependencies>
    <!-- Including both dependencies for jar and test-jar to get main src included. -->
    <dependency>
      <groupId>com.example.problem</groupId>
      <artifactId>animals</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>com.example.problem</groupId>
      <artifactId>animals</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>test-jar</type>
    </dependency>
  </dependencies>
</project>