I am currently attempting to write a Maven plugin using GMavenPlus (thank you @Keegan!) and Groovy 2.4.3. In a nutshell, the plugin parses a directory of SQL DDLs and generates output from those parsed DDLs
The Mojo itself works just fine when built, imported, and run within a full consuming project. Horrah!
The problem is with unit testing. When trying to unit test this Mojo, Maven POM vars like ${project.basedir}
are not being
expanded and thus the mojo is failing with an error like "File not found! [${project.basedir}/src/test/resources/ddl]". As
you can see from that error message, ${project.basedir}
was passed as a literal instead of being expanded.
I am currently using the Maven Plugin Testing Harness (with the fixed dependencies, see this blog), JUnit 4.12, and AssertJ 3.0.0 as my testing stack.
Any ideas or specific tricks to get things like project.basedir to expand in a unit test?
Thanks in advance!
Unit Test in Question:
import edge.SqlToScalaMojo
import org.junit.Before
import org.junit.Test
/**
* Created by medge on 6/15/15.
*/
class SqlToScalaMojoTest extends BaseMojoTest<SqlToScalaMojo> {
SqlToScalaMojo mojo
@Before
void setup() {
mojo = getMojo("parse-ddls")
}
@Test
void testMojoExecution() throws Exception {
assertThat mojo isNotNull()
mojo.execute()
}
}
BaseMojoTest.groovy (really just a convenience base class):
import org.apache.maven.plugin.AbstractMojo
import org.apache.maven.plugin.testing.MojoRule
import org.junit.Rule
/**
* Base Test class for Mojo tests. Extends {@link org.assertj.core.api.Assertions}
*
* If a type is given to this class then the result of #getMojo() does not have to be cast, reducing the amount of code
* to be written in the unit tests themselves.
*
* Created by medge on 6/5/15.
*/
abstract class BaseMojoTest<T extends AbstractMojo> extends org.assertj.core.api.Assertions {
/**
* MojoRule used to lookup Mojos
*/
@Rule public MojoRule rule = new MojoRule()
/**
* Get a configured mojo using the default pom file. Calls #getMojo(goal, getPom()) implicitly
*
* @param goal Goal to look up
* @return T configured Mojo
*/
T getMojo(String goal) {
getMojo(goal, getPom())
}
/**
* Get a configured mojo using the specified pom file
*
* @param goal Goal to look up
* @param pom POM file to use when configuring Mojo
* @return T configured Mojo
*/
T getMojo(String goal, File pom) {
T mojo = (T) rule.lookupMojo(goal, pom)
mojo
}
/**
* Default POM file if no custom path is given
*/
String defaultPomPath = "src/test/resources/plugin-config.xml"
/**
* Return a File reference containing the default POM file
*
* @return File
*/
File getPom() {
getPom(defaultPomPath)
}
/**
* Return a File reference containing the POM file found at the specified path. Implicitly asserts that the POM
* exists using <code>assertFile</code>
*
* @param path Path to user-defined POM (overrides the default if provided)
* @return File containing the specified POM.
*/
File getPom(String path) {
File _pom = getTestFile(path)
// Implicitly assert POM exists
assertFile(_pom)
// Then return the POM file
_pom
}
/**
* Convenience method to assert that a file is valid
*
* @param file File to validate
*/
static void assertFile(File file) {
assertThat file isNotNull()
assertThat file exists()
}
/**
* Get the current project's base directory. From {@link org.codehaus.plexus.PlexusTestCase}
*
* @return Base directory path
*/
static String getBaseDir() {
final String path = System.getProperty( "basedir" );
path ?: new File( "" ).getAbsolutePath();
}
/**
* Return a test file from the src/test/resources directory. Assumes the base directory is src/test/resources so the
* src/test/resources prefix can be omitted from the path if desired
*
* @param path File path
* @return File
*/
static File getTestFile(String path) {
File testFile
if(path.indexOf("src/test/resources/") > -1)
testFile = getTestFile(getBaseDir(), path)
else
testFile = getTestFile(getBaseDir(), "src/test/resources/${path}")
testFile
}
/**
* Retrieve a test file from the given baseDir/path
*
* @param baseDir String base directory to look in
* @param path String path to the file desired
* @return File
*/
static File getTestFile(String baseDir, String path) {
new File(baseDir, path)
}
}
Main POM file for the Mojo itself:
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edge</groupId>
<artifactId>parser-mojo</artifactId>
<version>0.0.3-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<properties>
<groovy.version>2.4.3</groovy.version>
<maven.version>3.3.3</maven.version>
<junit.version>4.12</junit.version>
<assertj.version>3.0.0</assertj.version>
</properties>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy.version}</version>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<!-- Dependencies for Maven Mojos -->
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.0.22</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>3.3.0</version>
<scope>test</scope>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<goals>
<goal>addSources</goal>
<goal>addTestSources</goal>
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>testGenerateStubs</goal>
<goal>testCompile</goal>
<goal>removeStubs</goal>
<goal>removeTestStubs</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.4</version>
<configuration>
<!-- see http://jira.codehaus.org/browse/MNG-5346 -->
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
<executions>
<execution>
<id>generate-descriptor</id>
<goals>
<goal>descriptor</goal>
</goals>
</execution>
<execution>
<id>help-goal</id>
<goals>
<goal>helpmojo</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Test POM used during the unit test:
<project>
<build>
<plugins>
<plugin>
<groupId>edge</groupId>
<artifactId>parser-mojo</artifactId>
<version>0.0.3-SNAPSHOT</version>
<configuration>
<template>${project.basedir}/src/test/resources/sample.template</template>
<inputDir>${project.basedir}/src/test/resources/ddl</inputDir>
<outputDir>${project.basedir}/src/test/resources/generated/</outputDir>
</configuration>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>parse-ddls</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Thanks!