On one of my work projects right now, I’m adding unit tests to a code generator. The easiest way to make sure the generated code works is to run mvn clean install. Of course, I want to do that from within the unit test and fail the test if the Maven run fails.
Fortunately, there’s Maven Invoker. Here’s how to use it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | private void invokeMavenInstall(File file) throws MavenInvocationException, CommandLineException { InvocationRequest request = new DefaultInvocationRequest(); request.setPomFile(file); request.setBatchMode(true); request.setDebug(true); // this prevents M2_HOME from being added in MavenCommandLineBuilder.setShellEnvironment, which then fails to // start mvn with "Error: Could not find or load main class org.codehaus.plexus.classworlds.launcher.Launcher" request.setShellEnvironmentInherited(false); request.setGoals(Collections.singletonList("install")); Invoker invoker = new DefaultInvoker(); invoker.setMavenHome(new File(System.getenv("M3_HOME"))); invoker.setOutputHandler(new SystemOutHandler()); invoker.setErrorHandler(new SystemOutHandler()); invoker.setLogger(new PrintStreamLogger(System.out, InvokerLogger.DEBUG)); InvocationResult result = invoker.execute(request); if (result.getExecutionException() != null) { throw result.getExecutionException(); } assertEquals(0, result.getExitCode()); } } |
The interesting bit here is the request.setShellEnvironmentInherited(false);
line. Without it, the MavenCommandLineBuilder.setShellEnvironment
method adds an environment variable M2_HOME to it, which prevents Maven from starting up.