From f8ae34185f65d607f7c3cacf6a08819e6138c819 Mon Sep 17 00:00:00 2001 From: Slawomir Jaranowski Date: Wed, 31 Dec 2025 14:43:29 +0100 Subject: [PATCH] Provide more default values by generated mocks - MojoExecution - will be a spy with current mojoDescriptor - MavenProject - will be a spy with default build path - Log - will be a spy - add some of static util methods from PlexusExtension --- .../api/plugin/testing/MojoExtension.java | 102 ++++++++++++++---- .../plugin/testing/ParametersMojoTest.java | 11 ++ .../testing/ProvidesInjectMojoTest.java | 19 +++- 3 files changed, 106 insertions(+), 26 deletions(-) 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 6853301..439ae0b 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 @@ -60,6 +60,9 @@ import org.apache.maven.execution.scope.internal.MojoExecutionScope; import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory; import org.apache.maven.lifecycle.internal.MojoDescriptorCreator; +import org.apache.maven.model.Build; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.Resource; import org.apache.maven.plugin.Mojo; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.PluginParameterExpressionEvaluator; @@ -226,7 +229,7 @@ public void beforeEach(ExtensionContext context) throws Exception { binder.install(new MavenProvidesModule(context.getRequiredTestInstance())); }); - addMock(plexusContainer, Log.class, () -> new MojoLogWrapper(LoggerFactory.getLogger("anonymous"))); + addMock(plexusContainer, Log.class, () -> spy(new MojoLogWrapper(LoggerFactory.getLogger("anonymous")))); MavenProject mavenProject = addMock(plexusContainer, MavenProject.class, this::mockMavenProject); MojoExecution mojoExecution = addMock(plexusContainer, MojoExecution.class, this::mockMojoExecution); MavenSession mavenSession = addMock(plexusContainer, MavenSession.class, this::mockMavenSession); @@ -257,7 +260,11 @@ public void beforeEach(ExtensionContext context) throws Exception { InterpolationFilterReader interpolationReader = new InterpolationFilterReader(reader, map, "${", "}")) { PluginDescriptor pluginDescriptor = new PluginDescriptorBuilder().build(interpolationReader); - + Plugin plugin = new Plugin(); + plugin.setGroupId(pluginDescriptor.getGroupId()); + plugin.setArtifactId(pluginDescriptor.getArtifactId()); + plugin.setVersion(pluginDescriptor.getVersion()); + pluginDescriptor.setPlugin(plugin); context.getStore(MOJO_EXTENSION).put(PluginDescriptor.class, pluginDescriptor); for (ComponentDescriptor desc : pluginDescriptor.getComponents()) { @@ -294,7 +301,7 @@ public void afterEach(ExtensionContext context) throws Exception { * @return a MojoExecution mock */ private MojoExecution mockMojoExecution() { - return Mockito.mock(MojoExecution.class); + return spy(new MojoExecution(null)); } /** @@ -315,8 +322,29 @@ private MavenSession mockMavenSession() { * @return a MavenProject mock */ private MavenProject mockMavenProject() { - MavenProject mavenProject = Mockito.mock(MavenProject.class); - lenient().when(mavenProject.getProperties()).thenReturn(new Properties()); + MavenProject mavenProject = spy(new MavenProject()); + Build build = spy(new Build()); + + build.setDirectory(Paths.get(getBasedir(), "target").toString()); + build.setOutputDirectory(Paths.get(getBasedir(), "target", "classes").toString()); + build.setTestOutputDirectory( + Paths.get(getBasedir(), "target", "test-classes").toString()); + build.setSourceDirectory(Paths.get(getBasedir(), "src", "main", "java").toString()); + build.setTestSourceDirectory( + Paths.get(getBasedir(), "src", "test", "java").toString()); + + Resource resource = spy(new Resource()); + resource.setDirectory(Paths.get(getBasedir(), "src", "main", "resource").toString()); + build.setResources(Arrays.asList(resource)); + + Resource testResource = spy(new Resource()); + testResource.setDirectory( + Paths.get(getBasedir(), "src", "test", "resource").toString()); + build.setTestResources(Arrays.asList(resource)); + + mavenProject.setBuild(build); + mavenProject.addCompileSourceRoot(build.getSourceDirectory()); + mavenProject.addTestCompileSourceRoot(build.getTestSourceDirectory()); return mavenProject; } @@ -335,32 +363,33 @@ private Mojo lookupMojo( String pom = injectMojo.pom(); Path basedir = Paths.get(getTestBasedir(extensionContext)); String[] coord = mojoCoordinates(goal, descriptor); - Xpp3Dom pomDom; + Xpp3Dom pomDom = null; + Path pomPath = null; if (pom.startsWith("file:")) { - Path path = basedir.resolve(pom.substring("file:".length())); - pomDom = Xpp3DomBuilder.build(new XmlStreamReader(path.toFile())); + pomPath = basedir.resolve(pom.substring("file:".length())); } else if (pom.startsWith("classpath:")) { URL url = holder.getResource(pom.substring("classpath:".length())); if (url == null) { throw new IllegalStateException("Unable to find pom on classpath: " + pom); } - pomDom = Xpp3DomBuilder.build(new XmlStreamReader(url.openStream())); + pomPath = Paths.get(url.toURI()); } else if (pom.contains("")) { pomDom = Xpp3DomBuilder.build(new StringReader(pom)); } else if (!pom.isEmpty()) { - Path path = basedir.resolve(pom); - pomDom = Xpp3DomBuilder.build(new XmlStreamReader(path.toFile())); + pomPath = basedir.resolve(pom); } else if (isBasedirSet(extensionContext)) { // only look for a pom.xml if basedir is explicitly set - Path path = basedir.resolve("pom.xml"); - if (Files.exists(path)) { - pomDom = Xpp3DomBuilder.build(new XmlStreamReader(path.toFile())); + pomPath = basedir.resolve("pom.xml"); + } + + if (pomDom == null) { + if (pomPath != null && Files.exists(pomPath)) { + pomDom = Xpp3DomBuilder.build(new XmlStreamReader(pomPath.toFile())); } else { pomDom = new Xpp3Dom(""); } - } else { - pomDom = new Xpp3Dom(""); } + Xpp3Dom pluginConfiguration = extractPluginConfiguration(coord[1], pomDom); if (!mojoParameters.isEmpty()) { List children = mojoParameters.stream() @@ -374,7 +403,7 @@ private Mojo lookupMojo( children.forEach(config::addChild); pluginConfiguration = Xpp3Dom.mergeXpp3Dom(config, pluginConfiguration); } - return lookupMojo(extensionContext, coord, pluginConfiguration, descriptor); + return lookupMojo(extensionContext, coord, pluginConfiguration, descriptor, pomPath); } private boolean isBasedirSet(ExtensionContext extensionContext) { @@ -396,7 +425,11 @@ protected String[] mojoCoordinates(String goal, PluginDescriptor pluginDescripto * lookup the mojo while we have all the relevent information */ protected Mojo lookupMojo( - ExtensionContext extensionContext, String[] coord, Xpp3Dom pluginConfiguration, PluginDescriptor descriptor) + ExtensionContext extensionContext, + String[] coord, + Xpp3Dom pluginConfiguration, + PluginDescriptor descriptor, + Path pomPath) throws Exception { PlexusContainer plexusContainer = getContainer(extensionContext); @@ -422,17 +455,26 @@ protected Mojo lookupMojo( if (mockingDetails(session).isMock()) { lenient().doReturn(mavenProject).when(session).getCurrentProject(); + lenient().doReturn(request.getLocalRepository()).when(session).getLocalRepository(); } if (mockingDetails(mavenProject).isMock()) { - lenient() - .doReturn(new File(getTestBasedir(extensionContext))) - .when(mavenProject) - .getBasedir(); + if (mockingDetails(mavenProject).isSpy() && pomPath != null) { + mavenProject.setFile(pomPath.toFile()); + } else { + lenient() + .doReturn(new File(getTestBasedir(extensionContext))) + .when(mavenProject) + .getBasedir(); + } } if (mojoDescriptor.isPresent() && mockingDetails(mojoExecution).isMock()) { - lenient().doReturn(mojoDescriptor.get()).when(mojoExecution).getMojoDescriptor(); + if (mockingDetails(mojoExecution).isSpy()) { + mojoExecution.setMojoDescriptor(mojoDescriptor.get()); + } else { + lenient().doReturn(mojoDescriptor.get()).when(mojoExecution).getMojoDescriptor(); + } } if (pluginConfiguration != null) { @@ -658,6 +700,20 @@ public static String getBasedir() { return PlexusExtension.getBasedir(); } + /** + * Gets the file according to base directory for test resources. + */ + public static File getTestFile(String path) { + return PlexusExtension.getTestFile(path); + } + + /** + * Gets the path according to base directory for test resources. + */ + public static String getTestPath(String path) { + return PlexusExtension.getTestPath(path); + } + /** * Convenience method to set values to variables in objects that don't have setters */ diff --git a/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/ParametersMojoTest.java b/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/ParametersMojoTest.java index 90eb789..f3105de 100644 --- a/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/ParametersMojoTest.java +++ b/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/ParametersMojoTest.java @@ -21,6 +21,7 @@ import javax.inject.Inject; import java.io.File; +import java.nio.file.Paths; import org.apache.maven.api.plugin.testing.Basedir; import org.apache.maven.api.plugin.testing.InjectMojo; @@ -243,4 +244,14 @@ void testMultipleResolvedParameters(ParametersMojo mojo, TestInfo testInfo) { assertNotNull(mojo); assertNotNull(testInfo); } + + @Test + @InjectMojo(goal = "parameters") + @MojoParameter(name = "plain", value = "${project.build.directory}/generated") + void projectBuildDirectoryShouldBeResolved(ParametersMojo mojo) { + assertEquals( + Paths.get(MojoExtension.getBasedir(), "target", "generated").normalize(), + Paths.get(mojo.getPlain()).normalize()); + assertDoesNotThrow(mojo::execute); + } } diff --git a/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/ProvidesInjectMojoTest.java b/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/ProvidesInjectMojoTest.java index b03ca09..6b0a468 100644 --- a/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/ProvidesInjectMojoTest.java +++ b/maven-plugin-testing-harness/src/test/java/org/apache/maven/plugin/testing/ProvidesInjectMojoTest.java @@ -26,13 +26,11 @@ import org.apache.maven.plugin.MojoExecution; import org.apache.maven.project.MavenProject; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; -@ExtendWith(MockitoExtension.class) @MojoTest public class ProvidesInjectMojoTest { @@ -60,4 +58,19 @@ public void bennShouldBeInjected(ProvidesInjectMojo mojo) { assertSame(mojoExecution, mojo.getMojoExecution()); assertSame(mojoExecution, mojo.getMojoExecutionFromBean()); } + + @Test + @InjectMojo(pom = POM, goal = "test:test-plugin:0.0.1-SNAPSHOT:provides") + public void defaultValuesShouldBeProvided(ProvidesInjectMojo mojo) { + assertNotNull(mojo); + assertNotNull(mojo.getProject().getBasedir()); + assertNotNull(mojo.getProject().getBuild().getOutputDirectory()); + assertNotNull(mojo.getProject().getBuild().getTestOutputDirectory()); + assertFalse(mojo.getProject().getBuild().getResources().isEmpty()); + assertFalse(mojo.getProject().getBuild().getTestResources().isEmpty()); + assertFalse(mojo.getProject().getCompileSourceRoots().isEmpty()); + assertFalse(mojo.getProject().getTestCompileSourceRoots().isEmpty()); + assertFalse(mojo.getProject().getResources().isEmpty()); + assertFalse(mojo.getProject().getTestResources().isEmpty()); + } }