You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2023/10/18 14:30:23 UTC
[maven-plugin-testing] branch master updated: [MPLUGINTESTING-84] Support Junit 5 + Maven 3 (#31)
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-plugin-testing.git
The following commit(s) were added to refs/heads/master by this push:
new c7c07ad [MPLUGINTESTING-84] Support Junit 5 + Maven 3 (#31)
c7c07ad is described below
commit c7c07ad079686bb219354f4d8708f6c62eaeff61
Author: Guillaume Nodet <gn...@apache.org>
AuthorDate: Wed Oct 18 16:30:18 2023 +0200
[MPLUGINTESTING-84] Support Junit 5 + Maven 3 (#31)
---
maven-plugin-testing-harness/pom.xml | 11 +-
.../maven/api/plugin/testing/MojoExtension.java | 39 ++----
.../maven/plugin/testing/AbstractMojoTestCase.java | 2 +-
.../maven/plugin/testing/junit5/InjectMojo.java | 35 ++++++
.../testing/junit5}/MojoExtension.java | 131 +++++++++------------
.../maven/plugin/testing/junit5/MojoParameter.java | 34 ++++++
.../plugin/testing/junit5/MojoParameters.java | 30 +++++
.../maven/plugin/testing/junit5/MojoTest.java | 34 ++++++
8 files changed, 206 insertions(+), 110 deletions(-)
diff --git a/maven-plugin-testing-harness/pom.xml b/maven-plugin-testing-harness/pom.xml
index 186330e..b6a5a4b 100644
--- a/maven-plugin-testing-harness/pom.xml
+++ b/maven-plugin-testing-harness/pom.xml
@@ -48,7 +48,7 @@ under the License.
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>${mavenVersion}</version>
- <scope>test</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
@@ -71,9 +71,14 @@ under the License.
<!-- plexus -->
<dependency>
- <groupId>org.apache.maven</groupId>
+ <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
- <version>${mavenVersion}</version>
+ <version>4.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-xml</artifactId>
+ <version>4.0.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java
index 4a32690..f0a4f09 100644
--- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java
+++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java
@@ -77,7 +77,12 @@ import org.junit.jupiter.api.extension.ParameterResolver;
import org.slf4j.LoggerFactory;
/**
+ * JUnit extension to help testing Mojos. The extension should be automatically registered
+ * by adding the {@link MojoTest} annotation on the test class.
*
+ * @see MojoTest
+ * @see InjectMojo
+ * @see MojoParameter
*/
public class MojoExtension extends PlexusExtension implements ParameterResolver {
@@ -134,15 +139,6 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
PluginDescriptor pluginDescriptor = new PluginDescriptorBuilder().build(interpolationReader);
- // Artifact artifact =
- // lookup( RepositorySystem.class ).createArtifact( pluginDescriptor.getGroupId(),
- // pluginDescriptor.getArtifactId(),
- // pluginDescriptor.getVersion(), ".jar" );
- //
- // artifact.setFile( getPluginArtifactFile() );
- // pluginDescriptor.setPluginArtifact( artifact );
- // pluginDescriptor.setArtifacts( Collections.singletonList( artifact ) );
-
context.getStore(ExtensionContext.Namespace.GLOBAL).put(PluginDescriptor.class, pluginDescriptor);
for (ComponentDescriptor<?> desc : pluginDescriptor.getComponents()) {
@@ -203,7 +199,7 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
}
/**
- * lookup the mojo while we have all of the relavent information
+ * lookup the mojo while we have all the relevent information
*/
protected Mojo lookupMojo(String[] coord, XmlNode pluginConfiguration, PluginDescriptor descriptor)
throws Exception {
@@ -319,13 +315,8 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
/**
* Convenience method to obtain the value of a variable on a mojo that might not have a getter.
- *
- * NOTE: the caller is responsible for casting to to what the desired type is.
- *
- * @param object
- * @param variable
- * @return object value of variable
- * @throws IllegalArgumentException
+ * <br>
+ * NOTE: the caller is responsible for casting to what the desired type is.
*/
public static Object getVariableValueFromObject(Object object, String variable) throws IllegalAccessException {
Field field = ReflectionUtils.getFieldByNameIncludingSuperclasses(variable, object.getClass());
@@ -335,11 +326,8 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
/**
* Convenience method to obtain all variables and values from the mojo (including its superclasses)
- *
+ * <br>
* Note: the values in the map are of type Object so the caller is responsible for casting to desired types.
- *
- * @param object
- * @return map of variable names and values
*/
public static Map<String, Object> getVariablesAndValuesFromObject(Object object) throws IllegalAccessException {
return getVariablesAndValuesFromObject(object.getClass(), object);
@@ -347,11 +335,9 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
/**
* Convenience method to obtain all variables and values from the mojo (including its superclasses)
- *
+ * <br>
* Note: the values in the map are of type Object so the caller is responsible for casting to desired types.
*
- * @param clazz
- * @param object
* @return map of variable names and values
*/
public static Map<String, Object> getVariablesAndValuesFromObject(Class<?> clazz, Object object)
@@ -371,11 +357,6 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
/**
* Convenience method to set values to variables in objects that don't have setters
- *
- * @param object
- * @param variable
- * @param value
- * @throws IllegalAccessException
*/
public static void setVariableValueToObject(Object object, String variable, Object value)
throws IllegalAccessException {
diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/AbstractMojoTestCase.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/AbstractMojoTestCase.java
index 8c46573..a163e5d 100644
--- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/AbstractMojoTestCase.java
+++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/AbstractMojoTestCase.java
@@ -36,7 +36,6 @@ import java.util.Map;
import java.util.Properties;
import com.google.inject.Module;
-import org.apache.commons.io.input.XmlStreamReader;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
@@ -75,6 +74,7 @@ import org.codehaus.plexus.util.InterpolationFilterReader;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.ReflectionUtils;
import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.XmlStreamReader;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/InjectMojo.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/InjectMojo.java
new file mode 100644
index 0000000..7b2fbdc
--- /dev/null
+++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/InjectMojo.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.plugin.testing.junit5;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface InjectMojo {
+
+ String goal();
+
+ String pom();
+
+ boolean empty() default false;
+}
diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoExtension.java
similarity index 79%
copy from maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java
copy to maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoExtension.java
index 4a32690..f5d2d21 100644
--- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java
+++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoExtension.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.maven.api.plugin.testing;
+package org.apache.maven.plugin.testing.junit5;
import java.io.BufferedReader;
import java.io.File;
@@ -39,23 +39,23 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.inject.internal.ProviderMethodsModule;
-import org.apache.maven.api.MojoExecution;
-import org.apache.maven.api.Project;
-import org.apache.maven.api.Session;
-import org.apache.maven.api.plugin.Log;
-import org.apache.maven.api.plugin.Mojo;
-import org.apache.maven.api.xml.XmlNode;
-import org.apache.maven.configuration.internal.EnhancedComponentConfigurator;
-import org.apache.maven.internal.impl.DefaultLog;
-import org.apache.maven.internal.xml.XmlNodeImpl;
+import org.apache.maven.api.plugin.testing.MojoTest;
+import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
-import org.apache.maven.plugin.PluginParameterExpressionEvaluatorV4;
+import org.apache.maven.plugin.Mojo;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.testing.ConfigurationException;
+import org.apache.maven.plugin.testing.MojoLogWrapper;
+import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.configurator.BasicComponentConfigurator;
import org.codehaus.plexus.component.configurator.ComponentConfigurator;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
@@ -77,7 +77,12 @@ import org.junit.jupiter.api.extension.ParameterResolver;
import org.slf4j.LoggerFactory;
/**
+ * JUnit extension to help testing Mojos. The extension should be automatically registered
+ * by adding the {@link org.apache.maven.api.plugin.testing.MojoTest} annotation on the test class.
*
+ * @see MojoTest
+ * @see org.apache.maven.api.plugin.testing.InjectMojo
+ * @see org.apache.maven.api.plugin.testing.MojoParameter
*/
public class MojoExtension extends PlexusExtension implements ParameterResolver {
@@ -120,7 +125,7 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
((DefaultPlexusContainer) getContainer()).addPlexusInjector(Collections.emptyList(), binder -> {
binder.install(ProviderMethodsModule.forObject(context.getRequiredTestInstance()));
binder.requestInjection(context.getRequiredTestInstance());
- binder.bind(Log.class).toInstance(new DefaultLog(LoggerFactory.getLogger("anonymous")));
+ binder.bind(Log.class).toInstance(new MojoLogWrapper(LoggerFactory.getLogger("anonymous")));
});
Map<Object, Object> map = getContainer().getContext().getContextData();
@@ -134,15 +139,6 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
PluginDescriptor pluginDescriptor = new PluginDescriptorBuilder().build(interpolationReader);
- // Artifact artifact =
- // lookup( RepositorySystem.class ).createArtifact( pluginDescriptor.getGroupId(),
- // pluginDescriptor.getArtifactId(),
- // pluginDescriptor.getVersion(), ".jar" );
- //
- // artifact.setFile( getPluginArtifactFile() );
- // pluginDescriptor.setPluginArtifact( artifact );
- // pluginDescriptor.setArtifacts( Collections.singletonList( artifact ) );
-
context.getStore(ExtensionContext.Namespace.GLOBAL).put(PluginDescriptor.class, pluginDescriptor);
for (ComponentDescriptor<?> desc : pluginDescriptor.getComponents()) {
@@ -177,13 +173,18 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
Path path = Paths.get(getBasedir()).resolve(pom);
pomDom = Xpp3DomBuilder.build(ReaderFactory.newXmlReader(path.toFile()));
}
- XmlNode pluginConfiguration = extractPluginConfiguration(coord[1], pomDom);
+ Xpp3Dom pluginConfiguration = extractPluginConfiguration(coord[1], pomDom);
if (!mojoParameters.isEmpty()) {
- List<XmlNode> children = mojoParameters.stream()
- .map(mp -> new XmlNodeImpl(mp.name(), mp.value()))
+ List<Xpp3Dom> children = mojoParameters.stream()
+ .map(mp -> {
+ Xpp3Dom c = new Xpp3Dom(mp.name());
+ c.setValue(mp.value());
+ return c;
+ })
.collect(Collectors.toList());
- XmlNode config = new XmlNodeImpl("configuration", null, null, children, null);
- pluginConfiguration = XmlNode.merge(config, pluginConfiguration);
+ Xpp3Dom config = new Xpp3Dom("configuration");
+ children.forEach(config::addChild);
+ pluginConfiguration = Xpp3Dom.mergeXpp3Dom(config, pluginConfiguration);
}
Mojo mojo = lookupMojo(coord, pluginConfiguration, descriptor);
return mojo;
@@ -203,9 +204,9 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
}
/**
- * lookup the mojo while we have all of the relavent information
+ * lookup the mojo while we have all the relevent information
*/
- protected Mojo lookupMojo(String[] coord, XmlNode pluginConfiguration, PluginDescriptor descriptor)
+ protected Mojo lookupMojo(String[] coord, Xpp3Dom pluginConfiguration, PluginDescriptor descriptor)
throws Exception {
// pluginkey = groupId : artifactId : version : goal
Mojo mojo = lookup(Mojo.class, coord[0] + ":" + coord[1] + ":" + coord[2] + ":" + coord[3]);
@@ -218,27 +219,25 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
}
}
if (pluginConfiguration != null) {
- Session session = getContainer().lookup(Session.class);
- Project project;
+ MavenSession session = getContainer().lookup(MavenSession.class);
+ MavenProject project;
try {
- project = getContainer().lookup(Project.class);
+ project = getContainer().lookup(MavenProject.class);
} catch (ComponentLookupException e) {
project = null;
}
- org.apache.maven.plugin.MojoExecution mojoExecution;
+ MojoExecution mojoExecution;
try {
- MojoExecution me = getContainer().lookup(MojoExecution.class);
- mojoExecution = new org.apache.maven.plugin.MojoExecution(
- new org.apache.maven.model.Plugin(me.getPlugin()), me.getGoal(), me.getExecutionId());
+ mojoExecution = getContainer().lookup(MojoExecution.class);
} catch (ComponentLookupException e) {
mojoExecution = null;
}
- ExpressionEvaluator evaluator = new WrapEvaluator(
- getContainer(), new PluginParameterExpressionEvaluatorV4(session, project, mojoExecution));
- ComponentConfigurator configurator = new EnhancedComponentConfigurator();
+ ExpressionEvaluator evaluator =
+ new WrapEvaluator(getContainer(), new PluginParameterExpressionEvaluator(session, mojoExecution));
+ ComponentConfigurator configurator = new BasicComponentConfigurator();
configurator.configureComponent(
mojo,
- new XmlPlexusConfiguration(new Xpp3Dom(pluginConfiguration)),
+ new XmlPlexusConfiguration(pluginConfiguration),
evaluator,
getContainer().getContainerRealm());
}
@@ -246,36 +245,29 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
return mojo;
}
- private XmlNode finalizeConfig(XmlNode config, MojoDescriptor mojoDescriptor) {
- List<XmlNode> children = new ArrayList<>();
+ private Xpp3Dom finalizeConfig(Xpp3Dom config, MojoDescriptor mojoDescriptor) {
+ List<Xpp3Dom> children = new ArrayList<>();
if (mojoDescriptor != null && mojoDescriptor.getParameters() != null) {
- XmlNode defaultConfiguration =
- MojoDescriptorCreator.convert(mojoDescriptor).getDom();
+ Xpp3Dom defaultConfiguration = MojoDescriptorCreator.convert(mojoDescriptor);
for (Parameter parameter : mojoDescriptor.getParameters()) {
- XmlNode parameterConfiguration = config.getChild(parameter.getName());
+ Xpp3Dom parameterConfiguration = config.getChild(parameter.getName());
if (parameterConfiguration == null) {
parameterConfiguration = config.getChild(parameter.getAlias());
}
- XmlNode parameterDefaults = defaultConfiguration.getChild(parameter.getName());
- parameterConfiguration = XmlNode.merge(parameterConfiguration, parameterDefaults, Boolean.TRUE);
+ Xpp3Dom parameterDefaults = defaultConfiguration.getChild(parameter.getName());
+ parameterConfiguration = Xpp3Dom.mergeXpp3Dom(parameterConfiguration, parameterDefaults, Boolean.TRUE);
if (parameterConfiguration != null) {
- Map<String, String> attributes = new HashMap<>(parameterConfiguration.getAttributes());
if (isEmpty(parameterConfiguration.getAttribute("implementation"))
&& !isEmpty(parameter.getImplementation())) {
- attributes.put("implementation", parameter.getImplementation());
+ parameterConfiguration.setAttribute("implementation", parameter.getImplementation());
}
- parameterConfiguration = new XmlNodeImpl(
- parameter.getName(),
- parameterConfiguration.getValue(),
- attributes,
- parameterConfiguration.getChildren(),
- parameterConfiguration.getInputLocation());
-
children.add(parameterConfiguration);
}
}
}
- return new XmlNodeImpl("configuration", null, null, children, null);
+ Xpp3Dom c = new Xpp3Dom("configuration");
+ children.forEach(c::addChild);
+ return c;
}
private boolean isEmpty(String str) {
@@ -290,7 +282,7 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
return Stream.of(element.getChildren());
}
- public static XmlNode extractPluginConfiguration(String artifactId, Xpp3Dom pomDom) throws Exception {
+ public static Xpp3Dom extractPluginConfiguration(String artifactId, Xpp3Dom pomDom) throws Exception {
Xpp3Dom pluginConfigurationElement = child(pomDom, "build")
.flatMap(buildElement -> child(buildElement, "plugins"))
.map(MojoExtension::children)
@@ -301,7 +293,7 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
.orElseThrow(
() -> new ConfigurationException("Cannot find a configuration element for a plugin with an "
+ "artifactId of " + artifactId + "."));
- return pluginConfigurationElement.getDom();
+ return pluginConfigurationElement;
}
/**
@@ -319,13 +311,8 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
/**
* Convenience method to obtain the value of a variable on a mojo that might not have a getter.
- *
- * NOTE: the caller is responsible for casting to to what the desired type is.
- *
- * @param object
- * @param variable
- * @return object value of variable
- * @throws IllegalArgumentException
+ * <br>
+ * Note: the caller is responsible for casting to what the desired type is.
*/
public static Object getVariableValueFromObject(Object object, String variable) throws IllegalAccessException {
Field field = ReflectionUtils.getFieldByNameIncludingSuperclasses(variable, object.getClass());
@@ -335,11 +322,8 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
/**
* Convenience method to obtain all variables and values from the mojo (including its superclasses)
- *
+ * <br>
* Note: the values in the map are of type Object so the caller is responsible for casting to desired types.
- *
- * @param object
- * @return map of variable names and values
*/
public static Map<String, Object> getVariablesAndValuesFromObject(Object object) throws IllegalAccessException {
return getVariablesAndValuesFromObject(object.getClass(), object);
@@ -347,11 +331,9 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
/**
* Convenience method to obtain all variables and values from the mojo (including its superclasses)
- *
+ * <br>
* Note: the values in the map are of type Object so the caller is responsible for casting to desired types.
*
- * @param clazz
- * @param object
* @return map of variable names and values
*/
public static Map<String, Object> getVariablesAndValuesFromObject(Class<?> clazz, Object object)
@@ -371,11 +353,6 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver
/**
* Convenience method to set values to variables in objects that don't have setters
- *
- * @param object
- * @param variable
- * @param value
- * @throws IllegalAccessException
*/
public static void setVariableValueToObject(Object object, String variable, Object value)
throws IllegalAccessException {
diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoParameter.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoParameter.java
new file mode 100644
index 0000000..a3a8294
--- /dev/null
+++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoParameter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.plugin.testing.junit5;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Mojo parameter
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(MojoParameters.class)
+public @interface MojoParameter {
+ String name();
+
+ String value();
+}
diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoParameters.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoParameters.java
new file mode 100644
index 0000000..33c0a23
--- /dev/null
+++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoParameters.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.plugin.testing.junit5;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Mojo parameters container
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MojoParameters {
+ MojoParameter[] value();
+}
diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoTest.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoTest.java
new file mode 100644
index 0000000..09461bd
--- /dev/null
+++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoTest.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.plugin.testing.junit5;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+
+/**
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(MojoExtension.class)
+@Target(ElementType.TYPE)
+public @interface MojoTest {}