How to trick maven plugin environment and / or project configuration

I want to write unit tests (junit4) for my maven plugin. All the examples I found use "AbstractMojoTestCase" (junit3 :-(). To get rid of this, I got the answer here . But the problem is how Mojos gets the instance:

MyMojo myMojo = (MyMojo) lookupMojo( "touch", pom ); 

This means that I need pom for each test case - pom is the input to the tests. But is there a way to make fun of (I would use Mockito) a project model somehow? Can lookupMojo(String groupId, String artifactId, String version, String goal, PlexusConfiguration pluginConfiguration) be a good starting point? In this case, I would make fun of "PlexusConfiguration", but what methods? Some maven-plugin testing doku use classes such as "MavenProjectStub". But I canโ€™t get a consistent view of how mojo is created and what it says about creation.

The perfect solution would be if I could just

 @inject MyMojo testObject; 

and just make fun of everything you need to make it work (primary I need @Parameters)

+6
source share
1 answer

Based on my experience writing the Maven plugin, there are two levels of plugin testing: through unit test (using mocks) and through integration tests (using the maven-invoker plugin).

For integration tests, the maven archetype for the new maven plugins is already a good example out of the box, just do the following and look at it:

  mvn archetype:generate \ -DgroupId=sample.plugin \ -DartifactId=hello-maven-plugin \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-plugin 

By default, you will receive integration tests in the profile. An example maven project (under src \ it \ simple-it \ pom.xml) that can fulfill your plugin goals will also be available. I propose also to provide the result of the integration test with additional restrictions in this pom.xml. For example: you can add a Maven Enforcer Plugin rule to check for created files, if that makes sense for your plugin.

To more accurately answer the question of how to write unit tests for custom maven plugins, this is the approach I use:

  • JUnit + Mockito.
  • Work in test mode using @RunWith (MockitoJUnitRunner.class)
  • Defined Mock Maven classes (MavenProject, Log, Build, DependencyNode, etc.) using @Mock annotations
  • Initiate and link your mock objects in the @Before method (usually the setUp () method)
  • Check your plugin :)

As an example, as a class variable of your unit test:

You may have the following mocked objects:
 @Mock private MavenProject project; @Mock private Log log; @Mock Build build; 

Then in your @Before method you need to add a large glue code as follows:

 Mockito.when(this.project.getBuild()).thenReturn(this.build); 

For example, I use Enforcer plugin to write some custom rules, so I need

 @Mock private EnforcerRuleHelper helper; 

And in the @Before method:

  Mockito.when(this.helper.evaluate("${project}")).thenReturn(this.project); Mockito.when(this.helper.getLog()).thenReturn(this.log); Mockito.when(this.project.getBuild()).thenReturn(this.build); Mockito.when(this.helper.getComponent(DependencyGraphBuilder.class)).thenReturn(this.graphBuilder); Mockito.when(this.graphBuilder.buildDependencyGraph(this.project, null)).thenReturn(this.node); 

Thus, these layouts will be easy to use in your tests. For example, you must have the first dummy test in order to test it for an empty assembly as follows (below when testing a custom Enforcer rule):

 @Test public void testEmptyBuild() throws Exception { try { this.rule.execute(this.helper); } catch (EnforcerRuleException e) { Assert.fail("Rule should not fail"); } } 

If you need to test the dependencies on your assembly, for example, you can write utility methods as follows:

 private static DependencyNode generateNode(String groupId, String artifactId, String version) { DependencyNode node = Mockito.mock(DependencyNode.class); Artifact artifact = Mockito.mock(Artifact.class); Mockito.when(node.getArtifact()).thenReturn(artifact); // mock artifact Mockito.when(artifact.getGroupId()).thenReturn(groupId); Mockito.when(artifact.getArtifactId()).thenReturn(artifactId); Mockito.when(artifact.getVersion()).thenReturn(version); return node; } 

To easily create dependencies in the dependency graph of your assembly, follow these steps:

 List<DependencyNode> nodes = new ArrayList<DependencyNode>(); nodes.add(generateNode("junit", "junit", "4.12")); Mockito.when(node.getChildren()).thenReturn(nodes); 

NOTE. You can improve the utility method if you need additional information (for example, a scope or a classifier for a dependency).

If you also need to make fun of the plugin configuration because you need to scan existing plugins and their configuration, for example, you can do this as follows:

 List<Plugin> plugins = new ArrayList<Plugin>(); Plugin p = new Plugin(); // no need to mock it p.setArtifactId("maven-surefire-plugin"); Xpp3Dom conf = new Xpp3Dom("configuration"); Xpp3Dom skip = new Xpp3Dom("skip"); skip.setValue("true"); conf.addChild(skip); p.setConfiguration(conf); plugins.add(p); Mockito.when(this.build.getPlugins()).thenReturn(plugins); 

Obviously, I will not consider all possible cases, but I am sure that you understand the approach and use. Hope this helps.

+5
source

Source: https://habr.com/ru/post/957039/


All Articles