将 JMockit 与第谷一起使用

Using JMockit with Tycho

我有几个 Eclipse 插件项目,我想使用 Maven 和 Tycho 进行编译。该项目可以在 github 找到。在那里您会看到三个项目及其 pom.xml 文件。我的目标是 运行 使用 JMockit 进行单元测试。

为了启动 Maven,我切换到 maven.parent 目录并执行 mvn clean verify,它会产生以下输出:

D:\maven-test\maventest.parent>mvn clean verify
[INFO] Scanning for projects...
[INFO] Computing target platform for MavenProject: maventest:maventest:1.0.0-SNAPSHOT @ D:\maven-test\maventest\pom.xml
[INFO] Adding repository ....censored....
[INFO] Adding repository ....censored....
[INFO] Resolving dependencies of MavenProject: maventest:maventest:1.0.0-SNAPSHOT @ D:\maven-test\maventest\pom.xml
[INFO] Resolving class path of MavenProject: maventest:maventest:1.0.0-SNAPSHOT @ D:\maven-test\maventest\pom.xml
[INFO] Computing target platform for MavenProject: maventest:test.maventest:1.0.0-SNAPSHOT @ D:\maven-test\test.maventest\pom.xml
[INFO] Resolving dependencies of MavenProject: maventest:test.maventest:1.0.0-SNAPSHOT @ D:\maven-test\test.maventest\pom.xml
[INFO] Resolving class path of MavenProject: maventest:test.maventest:1.0.0-SNAPSHOT @ D:\maven-test\test.maventest\pom.xml
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] maventest.parent
[INFO] maventest
[INFO] test.maventest
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maventest.parent 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maventest.parent ---
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maventest 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maventest ---
[INFO]
[INFO] --- tycho-packaging-plugin:0.24.0:build-qualifier (default-build-qualifier) @ maventest ---
[INFO] The project's OSGi version is 1.0.0.201512010744
[INFO]
[INFO] --- tycho-packaging-plugin:0.24.0:validate-id (default-validate-id) @ maventest ---
[INFO]
[INFO] --- tycho-packaging-plugin:0.24.0:validate-version (default-validate-version) @ maventest ---
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ maventest ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\maven-test\maventest\src\main\resources
[INFO]
[INFO] --- tycho-compiler-plugin:0.24.0:compile (default-compile) @ maventest ---
[INFO] Compiling 2 source files to D:\maven-test\maventest\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ maventest ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\maven-test\maventest\src\test\resources
[INFO]
[INFO] --- target-platform-configuration:0.24.0:target-platform (default-target-platform) @ maventest ---
[INFO]
[INFO] --- tycho-packaging-plugin:0.24.0:package-plugin (default-package-plugin) @ maventest ---
[INFO] Building jar: D:\maven-test\maventest\target\maventest-1.0.0-SNAPSHOT.jar
[INFO]
[INFO] --- tycho-p2-plugin:0.24.0:p2-metadata-default (default-p2-metadata-default) @ maventest ---
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building test.maventest 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ test.maventest ---
[INFO]
[INFO] --- tycho-packaging-plugin:0.24.0:build-qualifier (default-build-qualifier) @ test.maventest ---
[INFO] The project's OSGi version is 1.0.0.201512010744
[INFO]
[INFO] --- tycho-packaging-plugin:0.24.0:validate-id (default-validate-id) @ test.maventest ---
[INFO]
[INFO] --- tycho-packaging-plugin:0.24.0:validate-version (default-validate-version) @ test.maventest ---
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ test.maventest ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\maven-test\test.maventest\src\main\resources
[INFO]
[INFO] --- tycho-compiler-plugin:0.24.0:compile (default-compile) @ test.maventest ---
[INFO] Compiling 1 source file to D:\maven-test\test.maventest\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ test.maventest ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\maven-test\test.maventest\src\test\resources
[INFO]
[INFO] --- target-platform-configuration:0.24.0:target-platform (default-target-platform) @ test.maventest ---
[INFO]
[INFO] --- tycho-packaging-plugin:0.24.0:package-plugin (default-package-plugin) @ test.maventest ---
[INFO] Building jar: D:\maven-test\test.maventest\target\test.maventest-1.0.0-SNAPSHOT.jar
[INFO]
[INFO] --- tycho-p2-plugin:0.24.0:p2-metadata-default (default-p2-metadata-default) @ test.maventest ---
[INFO]
[INFO] --- tycho-surefire-plugin:0.24.0:test (default-test) @ test.maventest ---
[INFO] Expected eclipse log file: D:\maven-test\test.maventest\target\work\data\.metadata\.log
[INFO] Command line:
        [C:\Program Files\Java\jdk8\jre\bin\java.exe, -Dosgi.noShutdown=false, -Dosgi.os=win32, -Dosgi.ws=win32, -Dosgi.arch=x86_64, -javaagent:D:\maven-test\org.jmockit_1.20.0.jar, -Dosgi.clean=true,
 -jar, C:\Users\cludwig\.m2\repository\p2\osgi\bundle\org.eclipse.equinox.launcher.3.100.v20150511-1540\org.eclipse.equinox.launcher-1.3.100.v20150511-1540.jar, -data, D:\maven-test\test.maventest\t
arget\work\data, -install, D:\maven-test\test.maventest\target\work, -configuration, D:\maven-test\test.maventest\target\work\configuration, -application, org.eclipse.tycho.surefire.osgibooter.headles
stest, -testproperties, D:\maven-test\test.maventest\target\surefire.properties]

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running test.maventest.Foo_UnitTest
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.118 sec <<< FAILURE! - in test.maventest.Foo_UnitTest
initializationError(test.maventest.Foo_UnitTest)  Time elapsed: 0.002 sec  <<< ERROR!
java.lang.VerifyError: null
        at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
        at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170)
        at mockit.internal.startup.Startup.redefineMethods(Startup.java:242)
        at mockit.internal.startup.Startup.redefineMethods(Startup.java:236)
        at mockit.internal.mockups.MockClassSetup.applyClassModifications(MockClassSetup.java:134)
        at mockit.internal.mockups.MockClassSetup.redefineMethodsInClassHierarchy(MockClassSetup.java:91)
        at mockit.internal.mockups.MockClassSetup.redefineMethods(MockClassSetup.java:76)
        at mockit.MockUp.redefineMethods(MockUp.java:239)
        at mockit.MockUp.redefineClassOrImplementInterface(MockUp.java:221)
        at mockit.MockUp.<init>(MockUp.java:130)
        at mockit.integration.junit4.internal.RunNotifierDecorator.<init>(RunNotifierDecorator.java:21)
        at mockit.internal.startup.JMockitInitialization.loadInternalStartupMocksForJUnitIntegration(JMockitInitialization.java:35)
        at mockit.internal.startup.JMockitInitialization.initialize(JMockitInitialization.java:26)
        at mockit.internal.startup.Startup.applyStartupMocks(Startup.java:72)
        at mockit.internal.startup.Startup.reapplyStartupMocks(Startup.java:124)
        at mockit.internal.startup.Startup.getInstrumentation(Startup.java:188)
        at mockit.internal.startup.Startup.initializeIfPossible(Startup.java:198)
        at mockit.integration.junit4.JMockit.<clinit>(JMockit.java:21)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
        at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
        at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
        at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
        at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
        at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
        at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
        at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:262)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray2(ReflectionUtils.java:208)
        at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:156)
        at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:82)
        at org.eclipse.tycho.surefire.osgibooter.OsgiSurefireBooter.run(OsgiSurefireBooter.java:91)
        at org.eclipse.tycho.surefire.osgibooter.HeadlessTestApplication.run(HeadlessTestApplication.java:21)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.eclipse.equinox.internal.app.EclipseAppContainer.callMethodWithException(EclipseAppContainer.java:587)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:198)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:669)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:608)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1515)
        at org.eclipse.equinox.launcher.Main.main(Main.java:1488)


Results :

Tests in error:
  Foo_UnitTest.initializationError ╗ Verify

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] maventest.parent ................................... SUCCESS [  0.219 s]
[INFO] maventest .......................................... SUCCESS [  4.227 s]
[INFO] test.maventest ..................................... FAILURE [  4.320 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19.972 s
[INFO] Finished at: 2015-12-01T08:44:14+01:00
[INFO] Final Memory: 45M/405M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.eclipse.tycho:tycho-surefire-plugin:0.24.0:test (default-test) on project test.maventest: There are test failures.
[ERROR]
[ERROR] Please refer to D:\maven-test\test.maventest\target\surefire-reports for the individual test results.
[ERROR] -> [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/MojoFailureException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <goals> -rf :test.maventest

如果我删除父 POM 中的 -javaagent,则会出现另一个异常:

Running test.maventest.Foo_UnitTest
JMockit: Reinitializing under custom class loader org.eclipse.osgi.internal.loader.EquinoxClassLoader@1cbb87f3[org.jmockit:1.20.0(id=87)]
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:386)
        at sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:411)
Caused by: java.lang.VerifyError
        at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
        at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170)
        at mockit.internal.startup.Startup.redefineMethods(Startup.java:242)
        at mockit.internal.startup.Startup.redefineMethods(Startup.java:236)
        at mockit.internal.mockups.MockClassSetup.applyClassModifications(MockClassSetup.java:134)
        at mockit.internal.mockups.MockClassSetup.redefineMethodsInClassHierarchy(MockClassSetup.java:91)
        at mockit.internal.mockups.MockClassSetup.redefineMethods(MockClassSetup.java:76)
        at mockit.MockUp.redefineMethods(MockUp.java:239)
        at mockit.MockUp.redefineClassOrImplementInterface(MockUp.java:221)
        at mockit.MockUp.<init>(MockUp.java:130)
        at mockit.integration.junit4.internal.RunNotifierDecorator.<init>(RunNotifierDecorator.java:21)
        at mockit.internal.startup.JMockitInitialization.loadInternalStartupMocksForJUnitIntegration(JMockitInitialization.java:35)
        at mockit.internal.startup.JMockitInitialization.initialize(JMockitInitialization.java:26)
        at mockit.internal.startup.Startup.applyStartupMocks(Startup.java:72)
        at mockit.internal.startup.Startup.reapplyStartupMocks(Startup.java:124)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at mockit.internal.util.MethodReflection.invoke(MethodReflection.java:94)
        at mockit.internal.util.MethodReflection.invoke(MethodReflection.java:159)
        at mockit.internal.startup.Startup.reinitializeJMockitUnderCustomClassLoader(Startup.java:118)
        at mockit.internal.startup.Startup.agentmain(Startup.java:101)
        ... 6 more
java.lang.IllegalStateException: com.sun.tools.attach.AgentInitializationException: Agent JAR loaded but agent failed to initialize
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
        at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:262)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray2(ReflectionUtils.java:208)
        at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:156)
        at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:82)
        at org.eclipse.tycho.surefire.osgibooter.OsgiSurefireBooter.run(OsgiSurefireBooter.java:91)
        at org.eclipse.tycho.surefire.osgibooter.HeadlessTestApplication.run(HeadlessTestApplication.java:21)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.eclipse.equinox.internal.app.EclipseAppContainer.callMethodWithException(EclipseAppContainer.java:587)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:198)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:669)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:608)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1515)
        at org.eclipse.equinox.launcher.Main.main(Main.java:1488)
Caused by: com.sun.tools.attach.AgentInitializationException: Agent JAR loaded but agent failed to initialize
        ... 26 more
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.382 sec <<< FAILURE! - in test.maventest.Foo_UnitTest
test_value(test.maventest.Foo_UnitTest)  Time elapsed: 0.045 sec  <<< ERROR!
java.lang.IllegalStateException: Invalid place to record expectations
        at test.maventest.Foo_UnitTest.<init>(Foo_UnitTest.java:33)
        at test.maventest.Foo_UnitTest.getFoo(Foo_UnitTest.java:33)
        at test.maventest.Foo_UnitTest.test_value(Foo_UnitTest.java:25)


Results :

Tests in error:
  Foo_UnitTest.test_value:25->getFoo:33 ╗ IllegalState Invalid place to record e...

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0

Agent failed to start!
Exception in thread "Attach Listener"

所以我得出结论,-javaagent 是必需的。令人困惑:当使用 eclipse 运行 测试时,它就像一个魅力!

传递给 -javaagent 并因此用于 运行 测试的 jmockit-1.20.0.jar 与 eclipse 存储库中的完全相同。我还在测试中添加了 @RunWith(JMockit.class) 。正如here所述,我使用了所有三种方法。

那么你知道我能做什么吗?

我找到了解决方案:如果我使用 Run As -> JUnit Test 在 Eclipse 中执行测试,一切正常。如果我使用 Run As -> JUnit Plugin Test 执行测试,则会发生相同的错误。研究没有结果,JMockit 的支持是 cancelled ("won't fix").

由于 "normal" 测试运行良好,我可以使用 "normale" maven-surefire-plugin 而不是 tycho-surefire-plugin。唯一的区别是测试阶段(test 而不是 integration-test)并且没有 OSGi 环境(我不需要)。 POM文件中的解决方案如下。

parent.pom

<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>...</groupId>
    <artifactId>...</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <tycho-version>0.24.0</tycho-version>
        <junit-version>4.11</junit-version>
        <maven-surefire-version>2.19</maven-surefire-version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.eclipse.tycho</groupId>
                <artifactId>tycho-maven-plugin</artifactId>
                <version>${tycho-version}</version>
                <extensions>true</extensions>
            </plugin>

            <plugin>
                <groupId>org.eclipse.tycho</groupId>
                <artifactId>target-platform-configuration</artifactId>
                <version>${tycho-version}</version>
                <configuration>
                    <!-- Tell tycho where to find the *.target file. -->
                    <target>
                        <artifact>
                            <groupId>...</groupId>
                            <artifactId>...</artifactId>
                            <version>1.0.0-SNAPSHOT</version>
                        </artifact>
                    </target>

                    <environments>
                        <environment>
                            <os>win32</os>
                            <ws>win32</ws>
                            <arch>x86_64</arch>
                        </environment>
                    </environments>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.eclipse.tycho</groupId>
                <artifactId>tycho-surefire-plugin</artifactId>
                <version>${tycho-version}</version>
                <!-- we need to disable the tycho surefire plugin because it
                     runs an integration test. You can simulate it in Eclipse 
                     by executing a "JUnit Plugin test". This is not about to 
                     work with JMockit. Fortunately we do not need OSGi for 
                     the tests so we simply skip this phase. -->
                <executions>
                    <execution>
                        <id>default-test</id>
                        <phase>none</phase>
                    </execution>
                </executions>
            </plugin>

            <!-- Plugin to update the pom.xml to match the data found in MANIFEST.MF -->
            <plugin>
                <groupId>org.eclipse.tycho</groupId>
                <artifactId>tycho-versions-plugin</artifactId>
                <version>${tycho-version}</version>
            </plugin>

            <!-- to run tests in test plugins -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven-surefire-version}</version>
                <executions>
                    <execution>
                        <id>test</id>
                        <phase>test</phase>
                        <configuration>
                            <testClassesDirectory>target/classes</testClassesDirectory>
                        </configuration>
                        <goals>
                            <goal>test</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit-version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <modules>
        <!-- ... -->
    </modules>
</project>

所有其他 POM 文件都具有相同的结构:

<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>
    <artifactId>...</artifactId>
    <packaging>eclipse-plugin</packaging>

    <parent>
        <groupId>...</groupId>
        <artifactId>...</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>...</relativePath>
    </parent>
</project>

完美运行! :)