8686import org .mockito .Mockito ;
8787import org .slf4j .LoggerFactory ;
8888
89+ import static org .mockito .Mockito .lenient ;
90+
8991/**
9092 * JUnit's extension to help testing Mojos. The extension should be automatically registered
9193 * by adding the {@link MojoTest} annotation on the test class.
9698 */
9799public class MojoExtension extends PlexusExtension implements ParameterResolver {
98100
101+ // Namespace for storing/retrieving data related to MojoExtension
102+ private static final ExtensionContext .Namespace MOJO_EXTENSION = ExtensionContext .Namespace .create ("MojoExtension" );
103+
99104 @ Override
100105 public boolean supportsParameter (ParameterContext parameterContext , ExtensionContext extensionContext )
101106 throws ParameterResolutionException {
@@ -123,10 +128,9 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte
123128 .ifPresent (mojoParameters ::addAll );
124129
125130 Class <?> holder = parameterContext .getTarget ().get ().getClass ();
126- PluginDescriptor descriptor = extensionContext
127- .getStore (ExtensionContext .Namespace .GLOBAL )
128- .get (PluginDescriptor .class , PluginDescriptor .class );
129- return lookupMojo (holder , injectMojo , mojoParameters , descriptor );
131+ PluginDescriptor descriptor =
132+ extensionContext .getStore (MOJO_EXTENSION ).get (PluginDescriptor .class , PluginDescriptor .class );
133+ return lookupMojo (extensionContext , holder , injectMojo , mojoParameters , descriptor );
130134 } catch (Exception e ) {
131135 throw new ParameterResolutionException ("Unable to resolve parameter" , e );
132136 }
@@ -136,15 +140,13 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte
136140 public void beforeEach (ExtensionContext context ) throws Exception {
137141 String basedir = AnnotationSupport .findAnnotation (context .getElement ().get (), Basedir .class )
138142 .map (Basedir ::value )
139- .orElse (null );
140-
141- setTestBasedir (basedir );
143+ .orElseGet (PlexusExtension ::getBasedir );
142144
143- setContext ( context );
145+ setTestBasedir ( basedir , context );
144146
145- getContainer (). addComponent ( getContainer (), PlexusContainer . class . getName () );
147+ PlexusContainer plexusContainer = getContainer (context );
146148
147- ((DefaultPlexusContainer ) getContainer () ).addPlexusInjector (Collections .emptyList (), binder -> {
149+ ((DefaultPlexusContainer ) plexusContainer ).addPlexusInjector (Collections .emptyList (), binder -> {
148150 binder .install (ProviderMethodsModule .forObject (context .getRequiredTestInstance ()));
149151 binder .install (new MavenProvidesModule (context .getRequiredTestInstance ()));
150152 binder .requestInjection (context .getRequiredTestInstance ());
@@ -153,7 +155,7 @@ public void beforeEach(ExtensionContext context) throws Exception {
153155 binder .bind (MojoExecution .class ).toInstance (mockMojoExecution ());
154156 });
155157
156- Map <Object , Object > map = getContainer () .getContext ().getContextData ();
158+ Map <Object , Object > map = plexusContainer .getContext ().getContextData ();
157159
158160 ClassLoader classLoader = context .getRequiredTestClass ().getClassLoader ();
159161 try (InputStream is = Objects .requireNonNull (
@@ -164,10 +166,10 @@ public void beforeEach(ExtensionContext context) throws Exception {
164166
165167 PluginDescriptor pluginDescriptor = new PluginDescriptorBuilder ().build (interpolationReader );
166168
167- context .getStore (ExtensionContext . Namespace . GLOBAL ).put (PluginDescriptor .class , pluginDescriptor );
169+ context .getStore (MOJO_EXTENSION ).put (PluginDescriptor .class , pluginDescriptor );
168170
169171 for (ComponentDescriptor <?> desc : pluginDescriptor .getComponents ()) {
170- getContainer () .addComponentDescriptor (desc );
172+ plexusContainer .addComponentDescriptor (desc );
171173 }
172174 }
173175 }
@@ -178,7 +180,9 @@ public void beforeEach(ExtensionContext context) throws Exception {
178180 * @return a MojoExecution mock
179181 */
180182 private MojoExecution mockMojoExecution () {
181- return Mockito .mock (MojoExecution .class );
183+ MojoExecution mockExecution = Mockito .mock (MojoExecution .class );
184+ lenient ().when (mockExecution .getMojoDescriptor ()).thenReturn (new MojoDescriptor ());
185+ return mockExecution ;
182186 }
183187
184188 /**
@@ -188,8 +192,8 @@ private MojoExecution mockMojoExecution() {
188192 */
189193 private MavenSession mockMavenSession () {
190194 MavenSession session = Mockito .mock (MavenSession .class );
191- Mockito . lenient ().when (session .getUserProperties ()).thenReturn (new Properties ());
192- Mockito . lenient ().when (session .getSystemProperties ()).thenReturn (new Properties ());
195+ lenient ().when (session .getUserProperties ()).thenReturn (new Properties ());
196+ lenient ().when (session .getSystemProperties ()).thenReturn (new Properties ());
193197 return session ;
194198 }
195199
@@ -198,17 +202,19 @@ protected String getPluginDescriptorLocation() {
198202 }
199203
200204 private Mojo lookupMojo (
205+ ExtensionContext extensionContext ,
201206 Class <?> holder ,
202207 InjectMojo injectMojo ,
203208 Collection <MojoParameter > mojoParameters ,
204209 PluginDescriptor descriptor )
205210 throws Exception {
206211 String goal = injectMojo .goal ();
207212 String pom = injectMojo .pom ();
208- String [] coord = mojoCoordinates (goal );
213+ Path basedir = Paths .get (getTestBasedir (extensionContext ));
214+ String [] coord = mojoCoordinates (goal , descriptor );
209215 Xpp3Dom pomDom ;
210216 if (pom .startsWith ("file:" )) {
211- Path path = Paths . get ( getTestBasedir ()) .resolve (pom .substring ("file:" .length ()));
217+ Path path = basedir .resolve (pom .substring ("file:" .length ()));
212218 pomDom = Xpp3DomBuilder .build (new XmlStreamReader (path .toFile ()));
213219 } else if (pom .startsWith ("classpath:" )) {
214220 URL url = holder .getResource (pom .substring ("classpath:" .length ()));
@@ -218,9 +224,11 @@ private Mojo lookupMojo(
218224 pomDom = Xpp3DomBuilder .build (new XmlStreamReader (url .openStream ()));
219225 } else if (pom .contains ("<project>" )) {
220226 pomDom = Xpp3DomBuilder .build (new StringReader (pom ));
221- } else {
222- Path path = Paths . get ( getTestBasedir ()) .resolve (pom );
227+ } else if (! pom . isEmpty ()) {
228+ Path path = basedir .resolve (pom );
223229 pomDom = Xpp3DomBuilder .build (new XmlStreamReader (path .toFile ()));
230+ } else {
231+ pomDom = new Xpp3Dom ("" );
224232 }
225233 Xpp3Dom pluginConfiguration = extractPluginConfiguration (coord [1 ], pomDom );
226234 if (!mojoParameters .isEmpty ()) {
@@ -235,30 +243,29 @@ private Mojo lookupMojo(
235243 children .forEach (config ::addChild );
236244 pluginConfiguration = Xpp3Dom .mergeXpp3Dom (config , pluginConfiguration );
237245 }
238- Mojo mojo = lookupMojo (coord , pluginConfiguration , descriptor );
239- return mojo ;
246+ return lookupMojo (extensionContext , coord , pluginConfiguration , descriptor );
240247 }
241248
242- protected String [] mojoCoordinates (String goal ) throws Exception {
249+ protected String [] mojoCoordinates (String goal , PluginDescriptor pluginDescriptor ) throws Exception {
243250 if (goal .matches (".*:.*:.*:.*" )) {
244251 return goal .split (":" );
245252 } else {
246- Path pluginPom = Paths .get (getTestBasedir (), "pom.xml" );
247- Xpp3Dom pluginPomDom = Xpp3DomBuilder .build (new XmlStreamReader (pluginPom .toFile ()));
248- String artifactId = pluginPomDom .getChild ("artifactId" ).getValue ();
249- String groupId = resolveFromRootThenParent (pluginPomDom , "groupId" );
250- String version = resolveFromRootThenParent (pluginPomDom , "version" );
253+ String artifactId = pluginDescriptor .getArtifactId ();
254+ String groupId = pluginDescriptor .getGroupId ();
255+ String version = pluginDescriptor .getVersion ();
251256 return new String [] {groupId , artifactId , version , goal };
252257 }
253258 }
254259
255260 /**
256261 * lookup the mojo while we have all the relevent information
257262 */
258- protected Mojo lookupMojo (String [] coord , Xpp3Dom pluginConfiguration , PluginDescriptor descriptor )
263+ protected Mojo lookupMojo (
264+ ExtensionContext extensionContext , String [] coord , Xpp3Dom pluginConfiguration , PluginDescriptor descriptor )
259265 throws Exception {
266+ PlexusContainer plexusContainer = getContainer (extensionContext );
260267 // pluginkey = groupId : artifactId : version : goal
261- Mojo mojo = lookup (Mojo .class , coord [0 ] + ":" + coord [1 ] + ":" + coord [2 ] + ":" + coord [3 ]);
268+ Mojo mojo = plexusContainer . lookup (Mojo .class , coord [0 ] + ":" + coord [1 ] + ":" + coord [2 ] + ":" + coord [3 ]);
262269 for (MojoDescriptor mojoDescriptor : descriptor .getMojos ()) {
263270 if (Objects .equals (
264271 mojoDescriptor .getImplementation (), mojo .getClass ().getName ())) {
@@ -268,29 +275,29 @@ protected Mojo lookupMojo(String[] coord, Xpp3Dom pluginConfiguration, PluginDes
268275 }
269276 }
270277 if (pluginConfiguration != null ) {
271- MavenSession session = getContainer () .lookup (MavenSession .class );
278+ MavenSession session = plexusContainer .lookup (MavenSession .class );
272279 try {
273- getContainer () .lookup (MavenProject .class );
280+ plexusContainer .lookup (MavenProject .class );
274281 } catch (ComponentLookupException ignore ) {
275282 // nothing
276283 }
277284 MojoExecution mojoExecution ;
278285 try {
279- mojoExecution = getContainer () .lookup (MojoExecution .class );
286+ mojoExecution = plexusContainer .lookup (MojoExecution .class );
280287 } catch (ComponentLookupException e ) {
281288 mojoExecution = null ;
282289 }
283290 ExpressionEvaluator evaluator =
284- new WrapEvaluator (getContainer () , new PluginParameterExpressionEvaluator (session , mojoExecution ));
291+ new WrapEvaluator (plexusContainer , new PluginParameterExpressionEvaluator (session , mojoExecution ));
285292 ComponentConfigurator configurator = new BasicComponentConfigurator ();
286293 configurator .configureComponent (
287294 mojo ,
288295 new XmlPlexusConfiguration (pluginConfiguration ),
289296 evaluator ,
290- getContainer () .getContainerRealm ());
297+ plexusContainer .getContainerRealm ());
291298 }
292299
293- mojo .setLog (getContainer () .lookup (Log .class ));
300+ mojo .setLog (plexusContainer .lookup (Log .class ));
294301
295302 return mojo ;
296303 }
@@ -399,6 +406,14 @@ public static Map<String, Object> getVariablesAndValuesFromObject(Class<?> clazz
399406 return map ;
400407 }
401408
409+ /**
410+ * Gets the base directory for test resources.
411+ * If not explicitly set via {@link Basedir}, returns the plugin base directory.
412+ */
413+ public static String getBasedir () {
414+ return PlexusExtension .getBasedir ();
415+ }
416+
402417 /**
403418 * Convenience method to set values to variables in objects that don't have setters
404419 */
@@ -413,6 +428,7 @@ public static void setVariableValueToObject(Object object, String variable, Obje
413428 static class WrapEvaluator implements TypeAwareExpressionEvaluator {
414429
415430 private final PlexusContainer container ;
431+
416432 private final TypeAwareExpressionEvaluator evaluator ;
417433
418434 WrapEvaluator (PlexusContainer container , TypeAwareExpressionEvaluator evaluator ) {
0 commit comments