You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by sg...@apache.org on 2020/02/05 07:31:58 UTC

[freemarker-generator] branch FREEMARKER-129 updated: FREEMARKER-129 Re-format the source code

This is an automated email from the ASF dual-hosted git repository.

sgoeschl pushed a commit to branch FREEMARKER-129
in repository https://gitbox.apache.org/repos/asf/freemarker-generator.git


The following commit(s) were added to refs/heads/FREEMARKER-129 by this push:
     new 7022b26  FREEMARKER-129 Re-format the source code
7022b26 is described below

commit 7022b267f13cbe9f0262c08405a982a6047f868a
Author: Siegfried Goeschl <si...@gmail.com>
AuthorDate: Wed Feb 5 08:31:41 2020 +0100

    FREEMARKER-129 Re-format the source code
---
 .../freemarker/generator/maven/FactoryUtil.java    |  36 +-
 .../freemarker/generator/maven/FreeMarkerMojo.java | 177 +++---
 .../generator/maven/GeneratingFileVisitor.java     |  81 ++-
 .../generator/maven/JsonPropertiesProvider.java    |  99 ++--
 .../generator/maven/OutputGenerator.java           | 254 +++++----
 .../maven/OutputGeneratorPropertiesProvider.java   |  15 +-
 .../generator/maven/FreeMarkerMojoTest.java        | 629 +++++++++++----------
 .../generator/maven/GeneratingFileVisitorTest.java | 316 ++++++-----
 .../maven/JsonPropertiesProviderTest.java          | 151 ++---
 .../generator/maven/OutputGeneratorTest.java       | 520 ++++++++---------
 10 files changed, 1166 insertions(+), 1112 deletions(-)

diff --git a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/FactoryUtil.java b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/FactoryUtil.java
index ab97d53..a255d3f 100644
--- a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/FactoryUtil.java
+++ b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/FactoryUtil.java
@@ -19,32 +19,32 @@
 
 package org.apache.freemarker.generator.maven;
 
+import freemarker.template.Configuration;
+import freemarker.template.Version;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 
-import freemarker.template.Configuration;
-import freemarker.template.Version;
-
 /**
  * Simple utility class to call various constructors.
  * Needed because some jmockit features don't work well with constructors.
  */
 public class FactoryUtil {
 
-  public static Configuration createConfiguration(String freeMarkerVersion) {
-    return new Configuration(new Version(freeMarkerVersion));
-  }
-
-  public static File createFile(File parent, String child) {
-    return new File(parent, child);
-  }
-
-  public static FileInputStream createFileInputStream(File file) throws FileNotFoundException {
-    return new FileInputStream(file);
-  }
-  
-  public static File createFile(String name) {
-    return new File(name);
-  }
+    public static Configuration createConfiguration(String freeMarkerVersion) {
+        return new Configuration(new Version(freeMarkerVersion));
+    }
+
+    public static File createFile(File parent, String child) {
+        return new File(parent, child);
+    }
+
+    public static FileInputStream createFileInputStream(File file) throws FileNotFoundException {
+        return new FileInputStream(file);
+    }
+
+    public static File createFile(String name) {
+        return new File(name);
+    }
 }
diff --git a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/FreeMarkerMojo.java b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/FreeMarkerMojo.java
index c34ae99..4c9e96c 100644
--- a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/FreeMarkerMojo.java
+++ b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/FreeMarkerMojo.java
@@ -19,13 +19,8 @@
 
 package org.apache.freemarker.generator.maven;
 
-import java.io.File;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
+import freemarker.cache.FileTemplateLoader;
+import freemarker.template.Configuration;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecution;
@@ -35,91 +30,95 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 
-import freemarker.cache.FileTemplateLoader;
-import freemarker.template.Configuration;
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
 
 @Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
 public class FreeMarkerMojo extends AbstractMojo {
 
-  /** FreeMarker version string used to build FreeMarker Configuration instance. */
-  @Parameter
-  private String freeMarkerVersion;
-
-  @Parameter(defaultValue = "src/main/freemarker/generator")
-  private File sourceDirectory;
-
-  @Parameter(defaultValue = "src/main/freemarker/generator/template")
-  private File templateDirectory;
-
-  @Parameter(defaultValue = "src/main/freemarker/generator/generator")
-  private File generatorDirectory;
-
-  @Parameter(defaultValue = "target/generated-sources/freemarker/generator")
-  private File outputDirectory;
-
-  @Parameter(defaultValue = "${session}", readonly = true)
-  private MavenSession session;
-
-  @Parameter(defaultValue = "${mojoExecution}", readonly = true)
-  private MojoExecution mojo;
-
-  @Override
-  public void execute() throws MojoExecutionException, MojoFailureException {
-
-    if (freeMarkerVersion == null || freeMarkerVersion.length() == 0) {
-      throw new MojoExecutionException("freeMarkerVersion is required");
-    }
-
-    if (!generatorDirectory.isDirectory()) {
-      throw new MojoExecutionException("Required directory does not exist: " + generatorDirectory);
-    }
-
-    Configuration config = FactoryUtil.createConfiguration(freeMarkerVersion);
-
-    config.setDefaultEncoding("UTF-8");
-
-    if (!templateDirectory.isDirectory()) {
-      throw new MojoExecutionException("Required directory does not exist: " + templateDirectory);
-    }
-    try {
-      config.setTemplateLoader(new FileTemplateLoader(templateDirectory));
-    } catch (Throwable t) {
-      getLog().error("Could not establish file template loader for directory: " + templateDirectory, t);
-      throw new MojoExecutionException("Could not establish file template loader for directory: " + templateDirectory);
-    }
-
-    File freeMarkerProps = FactoryUtil.createFile(sourceDirectory, "freemarker.properties");
-    if (freeMarkerProps.isFile()) {
-      Properties configProperties = new Properties();
-      try (InputStream is = FactoryUtil.createFileInputStream(freeMarkerProps)) {
-        configProperties.load(is);
-      } catch (Throwable t) {
-        getLog().error("Failed to load " + freeMarkerProps, t);
-        throw new MojoExecutionException("Failed to load " + freeMarkerProps);
-      }
-      try {
-        config.setSettings(configProperties);
-      } catch (Throwable t) {
-        getLog().error("Invalid setting(s) in " + freeMarkerProps, t);
-        throw new MojoExecutionException("Invalid setting(s) in " + freeMarkerProps);
-      }
-    }
-    
-    if ("generate-sources".equals(mojo.getLifecyclePhase())) {
-      session.getCurrentProject().addCompileSourceRoot(outputDirectory.toString());
-    } else if ("generate-test-sources".equals(mojo.getLifecyclePhase())) {
-      session.getCurrentProject().addTestCompileSourceRoot(outputDirectory.toString());
-    }
-
-    Map<String, OutputGeneratorPropertiesProvider> extensionToBuilders = new HashMap<>(1);
-    extensionToBuilders.put(".json", JsonPropertiesProvider.create(generatorDirectory,templateDirectory,outputDirectory));
-
-    GeneratingFileVisitor fileVisitor = GeneratingFileVisitor.create(config, session, extensionToBuilders);
-    try {
-      Files.walkFileTree(generatorDirectory.toPath(), fileVisitor);
-    } catch (Throwable t) {
-      getLog().error("Failed to process files in generator dir: " + generatorDirectory, t);
-      throw new MojoExecutionException("Failed to process files in generator dir: " + generatorDirectory);
+    /** FreeMarker version string used to build FreeMarker Configuration instance. */
+    @Parameter
+    private String freeMarkerVersion;
+
+    @Parameter(defaultValue = "src/main/freemarker/generator")
+    private File sourceDirectory;
+
+    @Parameter(defaultValue = "src/main/freemarker/generator/template")
+    private File templateDirectory;
+
+    @Parameter(defaultValue = "src/main/freemarker/generator/generator")
+    private File generatorDirectory;
+
+    @Parameter(defaultValue = "target/generated-sources/freemarker/generator")
+    private File outputDirectory;
+
+    @Parameter(defaultValue = "${session}", readonly = true)
+    private MavenSession session;
+
+    @Parameter(defaultValue = "${mojoExecution}", readonly = true)
+    private MojoExecution mojo;
+
+    @Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+
+        if (freeMarkerVersion == null || freeMarkerVersion.length() == 0) {
+            throw new MojoExecutionException("freeMarkerVersion is required");
+        }
+
+        if (!generatorDirectory.isDirectory()) {
+            throw new MojoExecutionException("Required directory does not exist: " + generatorDirectory);
+        }
+
+        Configuration config = FactoryUtil.createConfiguration(freeMarkerVersion);
+
+        config.setDefaultEncoding("UTF-8");
+
+        if (!templateDirectory.isDirectory()) {
+            throw new MojoExecutionException("Required directory does not exist: " + templateDirectory);
+        }
+        try {
+            config.setTemplateLoader(new FileTemplateLoader(templateDirectory));
+        } catch (Throwable t) {
+            getLog().error("Could not establish file template loader for directory: " + templateDirectory, t);
+            throw new MojoExecutionException("Could not establish file template loader for directory: " + templateDirectory);
+        }
+
+        File freeMarkerProps = FactoryUtil.createFile(sourceDirectory, "freemarker.properties");
+        if (freeMarkerProps.isFile()) {
+            Properties configProperties = new Properties();
+            try (InputStream is = FactoryUtil.createFileInputStream(freeMarkerProps)) {
+                configProperties.load(is);
+            } catch (Throwable t) {
+                getLog().error("Failed to load " + freeMarkerProps, t);
+                throw new MojoExecutionException("Failed to load " + freeMarkerProps);
+            }
+            try {
+                config.setSettings(configProperties);
+            } catch (Throwable t) {
+                getLog().error("Invalid setting(s) in " + freeMarkerProps, t);
+                throw new MojoExecutionException("Invalid setting(s) in " + freeMarkerProps);
+            }
+        }
+
+        if ("generate-sources".equals(mojo.getLifecyclePhase())) {
+            session.getCurrentProject().addCompileSourceRoot(outputDirectory.toString());
+        } else if ("generate-test-sources".equals(mojo.getLifecyclePhase())) {
+            session.getCurrentProject().addTestCompileSourceRoot(outputDirectory.toString());
+        }
+
+        Map<String, OutputGeneratorPropertiesProvider> extensionToBuilders = new HashMap<>(1);
+        extensionToBuilders.put(".json", JsonPropertiesProvider.create(generatorDirectory, templateDirectory, outputDirectory));
+
+        GeneratingFileVisitor fileVisitor = GeneratingFileVisitor.create(config, session, extensionToBuilders);
+        try {
+            Files.walkFileTree(generatorDirectory.toPath(), fileVisitor);
+        } catch (Throwable t) {
+            getLog().error("Failed to process files in generator dir: " + generatorDirectory, t);
+            throw new MojoExecutionException("Failed to process files in generator dir: " + generatorDirectory);
+        }
     }
-  }
 }
diff --git a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/GeneratingFileVisitor.java b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/GeneratingFileVisitor.java
index 58a63ef..d71c871 100644
--- a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/GeneratingFileVisitor.java
+++ b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/GeneratingFileVisitor.java
@@ -19,60 +19,59 @@
 
 package org.apache.freemarker.generator.maven;
 
+import freemarker.template.Configuration;
+import org.apache.maven.execution.MavenSession;
+
 import java.nio.file.FileVisitResult;
 import java.nio.file.Path;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Map;
 
-import org.apache.maven.execution.MavenSession;
-
-import freemarker.template.Configuration;
-
 /**
  * FileVisitor designed to process json data files. The json file parsed into
- * a map and given to FreeMarker to 
+ * a map and given to FreeMarker to
  */
 public class GeneratingFileVisitor extends SimpleFileVisitor<Path> {
 
-  private final Configuration config;
-  private final MavenSession session;
-  private final long pomLastModifiedTimestamp;
-  private final Map<String, OutputGeneratorPropertiesProvider > extensionToBuilder;
+    private final Configuration config;
+    private final MavenSession session;
+    private final long pomLastModifiedTimestamp;
+    private final Map<String, OutputGeneratorPropertiesProvider> extensionToBuilder;
 
-  private GeneratingFileVisitor(Configuration config, MavenSession session, Map<String, OutputGeneratorPropertiesProvider> extensionToBuilder) {
-    this.config = config;
-    this.session = session;
-    this.extensionToBuilder = extensionToBuilder;
-    this.pomLastModifiedTimestamp = session.getAllProjects().stream()
-        .map(project->project.getFile().lastModified())
-        .reduce(Long::max)
-        .orElse(0L);
-  }
+    private GeneratingFileVisitor(Configuration config, MavenSession session, Map<String, OutputGeneratorPropertiesProvider> extensionToBuilder) {
+        this.config = config;
+        this.session = session;
+        this.extensionToBuilder = extensionToBuilder;
+        this.pomLastModifiedTimestamp = session.getAllProjects().stream()
+                .map(project -> project.getFile().lastModified())
+                .reduce(Long::max)
+                .orElse(0L);
+    }
 
-  /**
-   * Factory method that calls constructor, added to facilitate testing with jmockit.
-   */
-  public static GeneratingFileVisitor create(Configuration config, MavenSession session, Map<String, OutputGeneratorPropertiesProvider> extensionToBuilder) {
-    return new GeneratingFileVisitor(config, session, extensionToBuilder);
-  }
+    /**
+     * Factory method that calls constructor, added to facilitate testing with jmockit.
+     */
+    public static GeneratingFileVisitor create(Configuration config, MavenSession session, Map<String, OutputGeneratorPropertiesProvider> extensionToBuilder) {
+        return new GeneratingFileVisitor(config, session, extensionToBuilder);
+    }
 
-  @Override
-  public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
-    if (attrs.isRegularFile()) {
-      OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder()
-          .addGeneratorLocation(path)
-          .addPomLastModifiedTimestamp(pomLastModifiedTimestamp);
-      String fileName = path.getFileName().toString();
-      String extenstion = fileName.substring(fileName.lastIndexOf('.'));
-      OutputGeneratorPropertiesProvider pathProcessor = extensionToBuilder.get(extenstion);
-      if (pathProcessor == null) {
-        throw new RuntimeException("Unknown file extension: " + path);
-      }
-      pathProcessor.providePropertiesFromFile(path, builder);
-      builder.addToDataModel("pomProperties", session.getCurrentProject().getProperties());
-      builder.create().generate(config);
+    @Override
+    public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
+        if (attrs.isRegularFile()) {
+            OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder()
+                    .addGeneratorLocation(path)
+                    .addPomLastModifiedTimestamp(pomLastModifiedTimestamp);
+            String fileName = path.getFileName().toString();
+            String extenstion = fileName.substring(fileName.lastIndexOf('.'));
+            OutputGeneratorPropertiesProvider pathProcessor = extensionToBuilder.get(extenstion);
+            if (pathProcessor == null) {
+                throw new RuntimeException("Unknown file extension: " + path);
+            }
+            pathProcessor.providePropertiesFromFile(path, builder);
+            builder.addToDataModel("pomProperties", session.getCurrentProject().getProperties());
+            builder.create().generate(config);
+        }
+        return FileVisitResult.CONTINUE;
     }
-    return FileVisitResult.CONTINUE;
-  }
 }
diff --git a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/JsonPropertiesProvider.java b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/JsonPropertiesProvider.java
index fa57ddd..469870a 100644
--- a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/JsonPropertiesProvider.java
+++ b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/JsonPropertiesProvider.java
@@ -28,65 +28,68 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStreamReader;
 import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.util.HashMap;
 import java.util.Map;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 public class JsonPropertiesProvider implements OutputGeneratorPropertiesProvider {
-	private final Gson gson;
-	private final Type stringObjectMap;
-	private final File dataDir;
-	private final File templateDir;
-	private final File outputDir;
+    private final Gson gson;
+    private final Type stringObjectMap;
+    private final File dataDir;
+    private final File templateDir;
+    private final File outputDir;
 
-	private JsonPropertiesProvider(File dataDir, File templateDir, File outputDir) {
-		this.dataDir = dataDir;
-		this.templateDir = templateDir;
-		this.outputDir = outputDir;
-		gson = new GsonBuilder().setLenient().create();
-		stringObjectMap = new TypeToken<Map<String, Object>>() { } .getType();
-	}
+    private JsonPropertiesProvider(File dataDir, File templateDir, File outputDir) {
+        this.dataDir = dataDir;
+        this.templateDir = templateDir;
+        this.outputDir = outputDir;
+        gson = new GsonBuilder().setLenient().create();
+        stringObjectMap = new TypeToken<Map<String, Object>>() {}.getType();
+    }
 
-	public static JsonPropertiesProvider create(File dataDir, File templateDir, File outputDir) {
-		return new JsonPropertiesProvider(dataDir, templateDir, outputDir);
-	}
+    public static JsonPropertiesProvider create(File dataDir, File templateDir, File outputDir) {
+        return new JsonPropertiesProvider(dataDir, templateDir, outputDir);
+    }
 
-	@Override
-	public void providePropertiesFromFile(Path path, OutputGenerator.OutputGeneratorBuilder builder) {
-		File jsonDataFile = path.toFile();
-		Map<String,Object> data = parseJson(jsonDataFile);
+    @Override
+    public void providePropertiesFromFile(Path path, OutputGenerator.OutputGeneratorBuilder builder) {
+        File jsonDataFile = path.toFile();
+        Map<String, Object> data = parseJson(jsonDataFile);
 
-		Object obj = data.get("dataModel");
-		if (obj != null) {
-			builder.addDataModel((Map<String, Object>) obj);
-		} else {
-			builder.addDataModel(new HashMap<String,Object>());
-		}
+        Object obj = data.get("dataModel");
+        if (obj != null) {
+            builder.addDataModel((Map<String, Object>) obj);
+        } else {
+            builder.addDataModel(new HashMap<>());
+        }
 
-		obj = data.get("templateName");
-		if (obj == null) {
-			throw new RuntimeException("Require json data property not found: templateName");
-		}
-		builder.addTemplateLocation(templateDir.toPath().resolve(obj.toString()));
+        obj = data.get("templateName");
+        if (obj == null) {
+            throw new RuntimeException("Require json data property not found: templateName");
+        }
+        builder.addTemplateLocation(templateDir.toPath().resolve(obj.toString()));
 
-		String dataDirName = dataDir.getAbsolutePath();
-		String jsonFileName = jsonDataFile.getAbsolutePath();
-		if (!jsonFileName.startsWith(dataDirName)) {
-			throw new IllegalStateException("visitFile() given file not in sourceDirectory: " + jsonDataFile);
-		}
+        String dataDirName = dataDir.getAbsolutePath();
+        String jsonFileName = jsonDataFile.getAbsolutePath();
+        if (!jsonFileName.startsWith(dataDirName)) {
+            throw new IllegalStateException("visitFile() given file not in sourceDirectory: " + jsonDataFile);
+        }
 
-		String outputFileName = jsonFileName.substring(dataDirName.length()+1);
-		outputFileName = outputFileName.substring(0, outputFileName.length() - 5);
-		Path outputPath = outputDir.toPath();
-		Path resolved = outputPath.resolve(outputFileName);
-		builder.addOutputLocation(resolved);
-	}
+        String outputFileName = jsonFileName.substring(dataDirName.length() + 1);
+        outputFileName = outputFileName.substring(0, outputFileName.length() - 5);
+        Path outputPath = outputDir.toPath();
+        Path resolved = outputPath.resolve(outputFileName);
+        builder.addOutputLocation(resolved);
+    }
 
-	private Map<String, Object> parseJson(File jsonDataFile) {
-		try (JsonReader reader = new JsonReader(new InputStreamReader(new FileInputStream(jsonDataFile), "UTF-8"))) {
-			return gson.fromJson(reader, stringObjectMap);
-		} catch (Throwable t) {
-			throw new RuntimeException("Could not parse json data file: " + jsonDataFile, t);
-		}
-	}
+    private Map<String, Object> parseJson(File jsonDataFile) {
+        try (JsonReader reader = new JsonReader(new InputStreamReader(new FileInputStream(jsonDataFile), UTF_8))) {
+            return gson.fromJson(reader, stringObjectMap);
+        } catch (Throwable t) {
+            throw new RuntimeException("Could not parse json data file: " + jsonDataFile, t);
+        }
+    }
 }
diff --git a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/OutputGenerator.java b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/OutputGenerator.java
index 3eb9078..bec4f22 100644
--- a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/OutputGenerator.java
+++ b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/OutputGenerator.java
@@ -37,130 +37,138 @@ import java.util.Map;
  * <li>The location of the <b>output file</b></li>
  * <li>A <b>data model<b> used to fill out the template.</li>
  * </ul>
- *<p>Given these five pieces of information, the generator will generate a new output file, but only if any existing
+ * <p>Given these five pieces of information, the generator will generate a new output file, but only if any existing
  * generated file is not newer than the inputs (pom, generator, and template).</p>
  */
 class OutputGenerator {
-	public final long pomModifiedTimestamp;
-	public final Path generatorLocation;
-	public final Path templateLocation;
-	public final Path outputLocation;
-	public final Map<String,Object> dataModel;
-	private OutputGenerator(
-		 long pomModifiedTimestamp,
-		 Path generatorLocation,
-		 Path templateLocation,
-		 Path outputLocation,
-		 Map<String, Object> dataModel) {
-		this.pomModifiedTimestamp = pomModifiedTimestamp;
-		this.generatorLocation = generatorLocation;
-		this.templateLocation = templateLocation;
-		this.outputLocation = outputLocation;
-		this.dataModel = dataModel;
-	}
-
-	/**
-	 * Uses a fluent builder to make the code more legible in place.
-	 * Also allows the output generator to be built from multiple locations in source by passing the builder.
-	 * @return A new fluent builder for the OutputGenerator class.
-	 */
-	public static OutputGeneratorBuilder builder() {
-		return new OutputGeneratorBuilder();
-	}
-
-	public static class OutputGeneratorBuilder {
-		private long pomModifiedTimestamp = Long.MAX_VALUE;
-		private Path generatorLocation = null;
-		private Path templateLocation = null;
-		private Path outputLocation = null;
-		private Map<String,Object> dataModel = null;
-
-		public OutputGeneratorBuilder addPomLastModifiedTimestamp(long pomModifiedTimestamp) {
-			this.pomModifiedTimestamp = pomModifiedTimestamp;
-			return this;
-		}
-
-		public OutputGeneratorBuilder addGeneratorLocation(Path generatorLocation) {
-			this.generatorLocation = generatorLocation;
-			return this;
-		}
-
-		public OutputGeneratorBuilder addTemplateLocation(Path templateLocation) {
-			this.templateLocation = templateLocation;
-			return this;
-		}
-
-		public OutputGeneratorBuilder addOutputLocation(Path outputLocation) {
-			this.outputLocation = outputLocation;
-			return this;
-		}
-
-		public OutputGeneratorBuilder addDataModel(Map<String,Object> dataModel) {
-			this.dataModel = dataModel;
-			return this;
-		}
-
-		public OutputGeneratorBuilder addToDataModel(String key, Object val) {
-			if (this.dataModel == null) {
-				this.dataModel = new HashMap<>(4);
-			}
-			this.dataModel.put(key,val);
-			return this;
-		}
-
-		/**
-		 * @throws IllegalStateException if any of the parts of the OutputGenerator were not set.
-		 * @return A new output generator (which is immutable).
-		 */
-		public OutputGenerator create() {
-			if (pomModifiedTimestamp == Long.MAX_VALUE) throw new IllegalStateException("Must set the pomModifiedTimestamp");
-			if (generatorLocation == null) throw new IllegalStateException("Must set a non-null generatorLocation");
-			if (templateLocation == null) throw new IllegalStateException("Must set a non-null templateLocation");
-			if (outputLocation == null) throw new IllegalStateException("Must set a non-null outputLocation");
-			if (dataModel == null) throw new IllegalStateException("Must set a non-null dataModel");
-			return new OutputGenerator(pomModifiedTimestamp, generatorLocation, templateLocation, outputLocation, dataModel);
-		}
-	}
-
-	/**
-	 * <p>Generates an output by applying the model to the template.</p>
-	 * <p>Checks the ages of the inputs against an existing output file to early exit if there is no update.</p>
-	 * @param config Used to load the template from the template name.
-	 */
-	public void generate(Configuration config) {
-		//Use "createFile" for testing purposes only
-		File outputFile = FactoryUtil.createFile(outputLocation.toFile().toString());
-		File templateFile = templateLocation.toFile();
-		File generatorFile = generatorLocation.toFile();
-		if (outputFile.exists()) {
-			//early exit only if the output file is newer than all files that contribute to its generation
-			if (outputFile.lastModified() > generatorFile.lastModified()
-				 && outputFile.lastModified() > templateFile.lastModified()
-				 && outputFile.lastModified() > pomModifiedTimestamp) {
-				return;
-			}
-		} else {
-			File parentDir = outputFile.getParentFile();
-			if (parentDir.isFile()) {
-				throw new RuntimeException("Parent directory of output file is a file: " + parentDir.getAbsoluteFile());
-			}
-			parentDir.mkdirs();
-			if (!parentDir.isDirectory()) {
-				throw new RuntimeException("Could not create directory: " + parentDir.getAbsoluteFile());
-			}
-		}
-
-		Template template;
-		try {
-			template = config.getTemplate(templateFile.getName());
-		} catch (Throwable t) {
-			throw new RuntimeException("Could not read template: " + templateFile.getName(), t);
-		}
-
-		try (FileWriter writer = new FileWriter(outputFile)) {
-			template.process(dataModel, writer);
-		} catch (Throwable t) {
-			throw new RuntimeException("Could not process template associated with data file: " + generatorLocation, t);
-		}
-	}
+    public final long pomModifiedTimestamp;
+    public final Path generatorLocation;
+    public final Path templateLocation;
+    public final Path outputLocation;
+    public final Map<String, Object> dataModel;
+
+    private OutputGenerator(
+            long pomModifiedTimestamp,
+            Path generatorLocation,
+            Path templateLocation,
+            Path outputLocation,
+            Map<String, Object> dataModel) {
+        this.pomModifiedTimestamp = pomModifiedTimestamp;
+        this.generatorLocation = generatorLocation;
+        this.templateLocation = templateLocation;
+        this.outputLocation = outputLocation;
+        this.dataModel = dataModel;
+    }
+
+    /**
+     * Uses a fluent builder to make the code more legible in place.
+     * Also allows the output generator to be built from multiple locations in source by passing the builder.
+     *
+     * @return A new fluent builder for the OutputGenerator class.
+     */
+    public static OutputGeneratorBuilder builder() {
+        return new OutputGeneratorBuilder();
+    }
+
+    public static class OutputGeneratorBuilder {
+        private long pomModifiedTimestamp = Long.MAX_VALUE;
+        private Path generatorLocation = null;
+        private Path templateLocation = null;
+        private Path outputLocation = null;
+        private Map<String, Object> dataModel = null;
+
+        public OutputGeneratorBuilder addPomLastModifiedTimestamp(long pomModifiedTimestamp) {
+            this.pomModifiedTimestamp = pomModifiedTimestamp;
+            return this;
+        }
+
+        public OutputGeneratorBuilder addGeneratorLocation(Path generatorLocation) {
+            this.generatorLocation = generatorLocation;
+            return this;
+        }
+
+        public OutputGeneratorBuilder addTemplateLocation(Path templateLocation) {
+            this.templateLocation = templateLocation;
+            return this;
+        }
+
+        public OutputGeneratorBuilder addOutputLocation(Path outputLocation) {
+            this.outputLocation = outputLocation;
+            return this;
+        }
+
+        public OutputGeneratorBuilder addDataModel(Map<String, Object> dataModel) {
+            this.dataModel = dataModel;
+            return this;
+        }
+
+        public OutputGeneratorBuilder addToDataModel(String key, Object val) {
+            if (this.dataModel == null) {
+                this.dataModel = new HashMap<>(4);
+            }
+            this.dataModel.put(key, val);
+            return this;
+        }
+
+        /**
+         * @return A new output generator (which is immutable).
+         * @throws IllegalStateException if any of the parts of the OutputGenerator were not set.
+         */
+        public OutputGenerator create() {
+            if (pomModifiedTimestamp == Long.MAX_VALUE)
+                throw new IllegalStateException("Must set the pomModifiedTimestamp");
+            if (generatorLocation == null)
+                throw new IllegalStateException("Must set a non-null generatorLocation");
+            if (templateLocation == null)
+                throw new IllegalStateException("Must set a non-null templateLocation");
+            if (outputLocation == null)
+                throw new IllegalStateException("Must set a non-null outputLocation");
+            if (dataModel == null)
+                throw new IllegalStateException("Must set a non-null dataModel");
+            return new OutputGenerator(pomModifiedTimestamp, generatorLocation, templateLocation, outputLocation, dataModel);
+        }
+    }
+
+    /**
+     * <p>Generates an output by applying the model to the template.</p>
+     * <p>Checks the ages of the inputs against an existing output file to early exit if there is no update.</p>
+     *
+     * @param config Used to load the template from the template name.
+     */
+    public void generate(Configuration config) {
+        //Use "createFile" for testing purposes only
+        File outputFile = FactoryUtil.createFile(outputLocation.toFile().toString());
+        File templateFile = templateLocation.toFile();
+        File generatorFile = generatorLocation.toFile();
+        if (outputFile.exists()) {
+            //early exit only if the output file is newer than all files that contribute to its generation
+            if (outputFile.lastModified() > generatorFile.lastModified()
+                    && outputFile.lastModified() > templateFile.lastModified()
+                    && outputFile.lastModified() > pomModifiedTimestamp) {
+                return;
+            }
+        } else {
+            File parentDir = outputFile.getParentFile();
+            if (parentDir.isFile()) {
+                throw new RuntimeException("Parent directory of output file is a file: " + parentDir.getAbsoluteFile());
+            }
+            parentDir.mkdirs();
+            if (!parentDir.isDirectory()) {
+                throw new RuntimeException("Could not create directory: " + parentDir.getAbsoluteFile());
+            }
+        }
+
+        Template template;
+        try {
+            template = config.getTemplate(templateFile.getName());
+        } catch (Throwable t) {
+            throw new RuntimeException("Could not read template: " + templateFile.getName(), t);
+        }
+
+        try (FileWriter writer = new FileWriter(outputFile)) {
+            template.process(dataModel, writer);
+        } catch (Throwable t) {
+            throw new RuntimeException("Could not process template associated with data file: " + generatorLocation, t);
+        }
+    }
 }
diff --git a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/OutputGeneratorPropertiesProvider.java b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/OutputGeneratorPropertiesProvider.java
index dc0f111..25b929b 100644
--- a/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/OutputGeneratorPropertiesProvider.java
+++ b/freemarker-generator-maven-plugin/src/main/java/org/apache/freemarker/generator/maven/OutputGeneratorPropertiesProvider.java
@@ -22,11 +22,12 @@ package org.apache.freemarker.generator.maven;
 import java.nio.file.Path;
 
 public interface OutputGeneratorPropertiesProvider {
-	/**
-	 * Must add three properties to the builder: the <b>templateLocation</b>, <b>outputLocation</b>, and <b>dataModel</b>
-	 * The <b>pom updated timestamp</b> and <b>generatorLocation</b> are added elsewhere.
-	 * @param path The path to the generator file, to be used to decide on the three properties above.
-	 * @param builder The builder to which to add the properties.
-	 */
-	public void providePropertiesFromFile(Path path, OutputGenerator.OutputGeneratorBuilder builder);
+    /**
+     * Must add three properties to the builder: the <b>templateLocation</b>, <b>outputLocation</b>, and <b>dataModel</b>
+     * The <b>pom updated timestamp</b> and <b>generatorLocation</b> are added elsewhere.
+     *
+     * @param path    The path to the generator file, to be used to decide on the three properties above.
+     * @param builder The builder to which to add the properties.
+     */
+    void providePropertiesFromFile(Path path, OutputGenerator.OutputGeneratorBuilder builder);
 }
diff --git a/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/FreeMarkerMojoTest.java b/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/FreeMarkerMojoTest.java
index c88a25b..edc0910 100644
--- a/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/FreeMarkerMojoTest.java
+++ b/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/FreeMarkerMojoTest.java
@@ -19,7 +19,21 @@
 
 package org.apache.freemarker.generator.maven;
 
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import freemarker.cache.FileTemplateLoader;
+import freemarker.cache.TemplateLoader;
+import freemarker.template.Configuration;
+import mockit.Deencapsulation;
+import mockit.Expectations;
+import mockit.Mocked;
+import mockit.Verifications;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+import org.junit.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
 
 import java.io.File;
 import java.io.IOException;
@@ -30,316 +44,315 @@ import java.util.Comparator;
 import java.util.Map;
 import java.util.Properties;
 
-import org.apache.freemarker.generator.maven.FactoryUtil;
-import org.apache.freemarker.generator.maven.FreeMarkerMojo;
-import org.apache.freemarker.generator.maven.GeneratingFileVisitor;
-import org.apache.freemarker.generator.maven.OutputGeneratorPropertiesProvider;
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.plugin.MojoExecution;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.project.MavenProject;
-import org.junit.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import freemarker.cache.FileTemplateLoader;
-import freemarker.cache.TemplateLoader;
-import freemarker.template.Configuration;
-import mockit.Deencapsulation;
-import mockit.Expectations;
-import mockit.Mocked;
-import mockit.Verifications;
+import static org.assertj.core.api.Assertions.*;
 
 public class FreeMarkerMojoTest extends Assert {
 
-  private static final File TEST_OUTPUT_DIR = new File("target/test-output/freemarker-mojo");
-  private static final String FREEMARKER_VERSION = "2.3.29";
-  
-  @BeforeClass
-  public static void beforeClass() throws IOException {
-    // Clean output dir before each run.
-    if (TEST_OUTPUT_DIR.exists()) {
-      // Recursively delete output from previous run.
-      Files.walk(TEST_OUTPUT_DIR.toPath())
-       .sorted(Comparator.reverseOrder())
-       .map(Path::toFile)
-       .forEach(File::delete);
+    private static final File TEST_OUTPUT_DIR = new File("target/test-output/freemarker-mojo");
+    private static final String FREEMARKER_VERSION = "2.3.29";
+
+    @BeforeClass
+    public static void beforeClass() throws IOException {
+        // Clean output dir before each run.
+        if (TEST_OUTPUT_DIR.exists()) {
+            // Recursively delete output from previous run.
+            Files.walk(TEST_OUTPUT_DIR.toPath())
+                    .sorted(Comparator.reverseOrder())
+                    .map(Path::toFile)
+                    .forEach(File::delete);
+        }
+    }
+
+    @Test
+    public void executeTest(
+            @Mocked MavenSession session,
+            @Mocked MavenProject project,
+            @Mocked MojoExecution mojoExecution,
+            @Mocked GeneratingFileVisitor generatingFileVisitor,
+            @Mocked Files files
+    ) throws MojoExecutionException, MojoFailureException, IOException {
+
+        new Expectations(mojoExecution, generatingFileVisitor) {{
+            mojoExecution.getLifecyclePhase();
+            result = "generate-sources";
+            session.getCurrentProject();
+            result = project;
+        }};
+
+        FreeMarkerMojo mojo = new FreeMarkerMojo();
+
+        // Validate freeMarkerVersion is required.
+        assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
+            mojo.execute();
+        }).withMessage("freeMarkerVersion is required");
+
+        Deencapsulation.setField(mojo, "freeMarkerVersion", "");
+        assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
+            mojo.execute();
+        }).withMessage("freeMarkerVersion is required");
+
+        File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "executeTest");
+        Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
+        Deencapsulation.setField(mojo, "sourceDirectory", testCaseOutputDir);
+        Deencapsulation.setField(mojo, "templateDirectory", new File(testCaseOutputDir, "template"));
+        Deencapsulation.setField(mojo, "generatorDirectory", new File(testCaseOutputDir, "data"));
+        Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
+        Deencapsulation.setField(mojo, "mojo", mojoExecution);
+        Deencapsulation.setField(mojo, "session", session);
+
+        // Validate source directory.
+        assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
+            mojo.execute();
+        }).withMessage("Required directory does not exist: target/test-output/freemarker-mojo/executeTest/data");
+
+        new File(testCaseOutputDir, "data").mkdirs();
+        assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
+            mojo.execute();
+        }).withMessage("Required directory does not exist: target/test-output/freemarker-mojo/executeTest/template");
+        new File(testCaseOutputDir, "template").mkdirs();
+
+        // Validate minimum configuration.
+        mojo.execute();
+
+        new Verifications() {{
+            project.addCompileSourceRoot("target/test-output/freemarker-mojo/executeTest/generated-files");
+            times = 1;
+
+            Configuration config;
+            MavenSession capturedSession;
+            Map<String, OutputGeneratorPropertiesProvider> builders;
+
+            GeneratingFileVisitor.create(
+                    config = withCapture(),
+                    capturedSession = withCapture(),
+                    builders = withCapture());
+            times = 1;
+
+            assertEquals("UTF-8", config.getDefaultEncoding());
+            assertEquals(session, capturedSession);
+            TemplateLoader loader = config.getTemplateLoader();
+            assertTrue(loader instanceof FileTemplateLoader);
+
+            Path path;
+            FileVisitor<Path> fileVisitor;
+
+            Files.walkFileTree(path = withCapture(), fileVisitor = withCapture());
+            times = 1;
+
+            assertEquals(new File(testCaseOutputDir, "data").toPath(), path);
+            assertTrue(fileVisitor instanceof GeneratingFileVisitor);
+        }};
+    }
+
+    @Test
+    public void execute_generateTestSourceTest(
+            @Mocked MavenSession session,
+            @Mocked MavenProject project,
+            @Mocked MojoExecution mojoExecution,
+            @Mocked GeneratingFileVisitor generatingFileVisitor,
+            @Mocked Files files
+    ) throws MojoExecutionException, MojoFailureException, IOException {
+
+        new Expectations(mojoExecution, generatingFileVisitor) {{
+            mojoExecution.getLifecyclePhase();
+            result = "generate-test-sources";
+            session.getCurrentProject();
+            result = project;
+        }};
+
+        FreeMarkerMojo mojo = new FreeMarkerMojo();
+
+        File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "generateTestSourceTest");
+        Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
+        Deencapsulation.setField(mojo, "sourceDirectory", testCaseOutputDir);
+        Deencapsulation.setField(mojo, "templateDirectory", new File(testCaseOutputDir, "template"));
+        Deencapsulation.setField(mojo, "generatorDirectory", new File(testCaseOutputDir, "data"));
+        Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
+        Deencapsulation.setField(mojo, "mojo", mojoExecution);
+        Deencapsulation.setField(mojo, "session", session);
+
+        new File(testCaseOutputDir, "data").mkdirs();
+        new File(testCaseOutputDir, "template").mkdirs();
+
+        mojo.execute();
+
+        new Verifications() {{
+            project.addTestCompileSourceRoot("target/test-output/freemarker-mojo/generateTestSourceTest/generated-files");
+            times = 1;
+        }};
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void execute_walkFileTreeExceptionTest(
+            @Mocked MavenSession session,
+            @Mocked MavenProject project,
+            @Mocked MojoExecution mojoExecution,
+            @Mocked GeneratingFileVisitor generatingFileVisitor,
+            @Mocked Files files
+    ) throws MojoExecutionException, MojoFailureException, IOException {
+
+        new Expectations(mojoExecution, generatingFileVisitor) {{
+            mojoExecution.getLifecyclePhase();
+            result = "generate-test-sources";
+            session.getCurrentProject();
+            result = project;
+            Files.walkFileTree((Path) any, (FileVisitor) any);
+            result = new RuntimeException("test exception");
+        }};
+
+        FreeMarkerMojo mojo = new FreeMarkerMojo();
+
+        File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "generateTestSourceTest");
+        Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
+        Deencapsulation.setField(mojo, "sourceDirectory", testCaseOutputDir);
+        Deencapsulation.setField(mojo, "templateDirectory", new File(testCaseOutputDir, "template"));
+        Deencapsulation.setField(mojo, "generatorDirectory", new File(testCaseOutputDir, "data"));
+        Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
+        Deencapsulation.setField(mojo, "mojo", mojoExecution);
+        Deencapsulation.setField(mojo, "session", session);
+
+        new File(testCaseOutputDir, "data").mkdirs();
+        new File(testCaseOutputDir, "template").mkdirs();
+
+        assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
+            mojo.execute();
+        })
+                .withMessage("Failed to process files in generator dir: target/test-output/freemarker-mojo/generateTestSourceTest/data");
+    }
+
+    @Test
+    public void execute_setTemplateLoaderExceptionTest(
+            @Mocked MavenSession session,
+            @Mocked MavenProject project,
+            @Mocked MojoExecution mojoExecution,
+            @Mocked FactoryUtil factoryUtil,
+            @Mocked Configuration config) {
+
+        new Expectations(config, FactoryUtil.class) {{
+            FactoryUtil.createConfiguration(FREEMARKER_VERSION);
+            result = config;
+            config.setTemplateLoader((TemplateLoader) any);
+            result = new RuntimeException("test exception");
+        }};
+
+        FreeMarkerMojo mojo = new FreeMarkerMojo();
+
+        File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "setTemplateLoaderException");
+
+        Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
+        Deencapsulation.setField(mojo, "sourceDirectory", testCaseOutputDir);
+        Deencapsulation.setField(mojo, "templateDirectory", new File(testCaseOutputDir, "template"));
+        Deencapsulation.setField(mojo, "generatorDirectory", new File(testCaseOutputDir, "data"));
+        Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
+        Deencapsulation.setField(mojo, "mojo", mojoExecution);
+        Deencapsulation.setField(mojo, "session", session);
+
+        new File(testCaseOutputDir, "data").mkdirs();
+        new File(testCaseOutputDir, "template").mkdirs();
+
+        assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
+            mojo.execute();
+        })
+                .withMessage("Could not establish file template loader for directory: target/test-output/freemarker-mojo/setTemplateLoaderException/template");
     }
-  }
-
-  @Test
-  public void executeTest(
-      @Mocked MavenSession session,
-      @Mocked MavenProject project,
-      @Mocked MojoExecution mojoExecution,
-      @Mocked GeneratingFileVisitor generatingFileVisitor,
-      @Mocked Files files
-      ) throws MojoExecutionException, MojoFailureException, IOException {
-
-    new Expectations(mojoExecution, generatingFileVisitor) {{
-      mojoExecution.getLifecyclePhase(); result = "generate-sources";
-      session.getCurrentProject(); result = project;
-    }};
-
-    FreeMarkerMojo mojo = new FreeMarkerMojo();
-    
-    // Validate freeMarkerVersion is required.
-    assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
-      mojo.execute();
-    }).withMessage("freeMarkerVersion is required");
-    
-    Deencapsulation.setField(mojo, "freeMarkerVersion", "");
-    assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
-      mojo.execute();
-    }).withMessage("freeMarkerVersion is required");
-
-    File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "executeTest");
-    Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
-    Deencapsulation.setField(mojo, "sourceDirectory", testCaseOutputDir);
-    Deencapsulation.setField(mojo, "templateDirectory", new File(testCaseOutputDir, "template"));
-    Deencapsulation.setField(mojo, "generatorDirectory", new File(testCaseOutputDir, "data"));
-    Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
-    Deencapsulation.setField(mojo, "mojo", mojoExecution);
-    Deencapsulation.setField(mojo, "session", session);
-
-    // Validate source directory.
-    assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
-      mojo.execute();
-    }).withMessage("Required directory does not exist: target/test-output/freemarker-mojo/executeTest/data");
-    
-    new File(testCaseOutputDir, "data").mkdirs();
-    assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
-      mojo.execute();
-    }).withMessage("Required directory does not exist: target/test-output/freemarker-mojo/executeTest/template");
-    new File(testCaseOutputDir, "template").mkdirs();
-    
-    // Validate minimum configuration.
-    mojo.execute();
-    
-    new Verifications() {{
-      project.addCompileSourceRoot("target/test-output/freemarker-mojo/executeTest/generated-files"); times = 1;
-
-      Configuration config;
-      MavenSession capturedSession;
-      Map<String, OutputGeneratorPropertiesProvider> builders;
-
-      GeneratingFileVisitor.create(
-          config = withCapture(), 
-          capturedSession = withCapture(), 
-          builders = withCapture()); times = 1;
-
-      assertEquals("UTF-8", config.getDefaultEncoding());
-      assertEquals(session, capturedSession);
-      TemplateLoader loader = config.getTemplateLoader();
-      assertTrue(loader instanceof FileTemplateLoader);
-
-      Path path;
-      FileVisitor<Path> fileVisitor;
-      
-      Files.walkFileTree(path = withCapture(), fileVisitor = withCapture()); times = 1;
-      
-      assertEquals(new File(testCaseOutputDir, "data").toPath(), path);
-      assertTrue(fileVisitor instanceof GeneratingFileVisitor);
-    }};
-  }
-  
-  @Test
-  public void execute_generateTestSourceTest(
-      @Mocked MavenSession session,
-      @Mocked MavenProject project,
-      @Mocked MojoExecution mojoExecution,
-      @Mocked GeneratingFileVisitor generatingFileVisitor,
-      @Mocked Files files
-      ) throws MojoExecutionException, MojoFailureException, IOException {
-
-    new Expectations(mojoExecution, generatingFileVisitor) {{
-      mojoExecution.getLifecyclePhase(); result = "generate-test-sources";
-      session.getCurrentProject(); result = project;
-    }};
-
-    FreeMarkerMojo mojo = new FreeMarkerMojo();
-    
-    File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "generateTestSourceTest");
-    Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
-    Deencapsulation.setField(mojo, "sourceDirectory", testCaseOutputDir);
-    Deencapsulation.setField(mojo, "templateDirectory", new File(testCaseOutputDir, "template"));
-    Deencapsulation.setField(mojo, "generatorDirectory", new File(testCaseOutputDir, "data"));
-    Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
-    Deencapsulation.setField(mojo, "mojo", mojoExecution);
-    Deencapsulation.setField(mojo, "session", session);
-
-    new File(testCaseOutputDir, "data").mkdirs();
-    new File(testCaseOutputDir, "template").mkdirs();
-    
-    mojo.execute();
-    
-    new Verifications() {{
-      project.addTestCompileSourceRoot("target/test-output/freemarker-mojo/generateTestSourceTest/generated-files"); times = 1;
-    }};
-  }
-
-  @SuppressWarnings({"rawtypes", "unchecked"})
-  @Test
-  public void execute_walkFileTreeExceptionTest(
-      @Mocked MavenSession session,
-      @Mocked MavenProject project,
-      @Mocked MojoExecution mojoExecution,
-      @Mocked GeneratingFileVisitor generatingFileVisitor,
-      @Mocked Files files
-      ) throws MojoExecutionException, MojoFailureException, IOException {
-
-    new Expectations(mojoExecution, generatingFileVisitor) {{
-      mojoExecution.getLifecyclePhase(); result = "generate-test-sources";
-      session.getCurrentProject(); result = project;
-      Files.walkFileTree((Path) any,(FileVisitor) any); result = new RuntimeException("test exception");
-    }};
-
-    FreeMarkerMojo mojo = new FreeMarkerMojo();
-    
-    File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "generateTestSourceTest");
-    Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
-    Deencapsulation.setField(mojo, "sourceDirectory", testCaseOutputDir);
-    Deencapsulation.setField(mojo, "templateDirectory", new File(testCaseOutputDir, "template"));
-    Deencapsulation.setField(mojo, "generatorDirectory", new File(testCaseOutputDir, "data"));
-    Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
-    Deencapsulation.setField(mojo, "mojo", mojoExecution);
-    Deencapsulation.setField(mojo, "session", session);
-
-    new File(testCaseOutputDir, "data").mkdirs();
-    new File(testCaseOutputDir, "template").mkdirs();
-    
-    assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
-      mojo.execute();
-    }).withMessage("Failed to process files in generator dir: target/test-output/freemarker-mojo/generateTestSourceTest/data");
-  }
-  
-  @Test
-  public void execute_setTemplateLoaderExceptionTest(
-      @Mocked MavenSession session,
-      @Mocked MavenProject project,
-      @Mocked MojoExecution mojoExecution,
-      @Mocked FactoryUtil factoryUtil,
-      @Mocked Configuration config) {
-    
-    new Expectations(config, FactoryUtil.class) {{
-      FactoryUtil.createConfiguration(FREEMARKER_VERSION); result = config;
-      config.setTemplateLoader((TemplateLoader) any); result = new RuntimeException("test exception");
-    }};
-
-    FreeMarkerMojo mojo = new FreeMarkerMojo();
-
-    File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "setTemplateLoaderException");
-
-    Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
-    Deencapsulation.setField(mojo, "sourceDirectory", testCaseOutputDir);
-    Deencapsulation.setField(mojo, "templateDirectory", new File(testCaseOutputDir, "template"));
-    Deencapsulation.setField(mojo, "generatorDirectory", new File(testCaseOutputDir, "data"));
-    Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
-    Deencapsulation.setField(mojo, "mojo", mojoExecution);
-    Deencapsulation.setField(mojo, "session", session);
-
-    new File(testCaseOutputDir, "data").mkdirs();
-    new File(testCaseOutputDir, "template").mkdirs();
-
-    assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
-      mojo.execute();
-    }).withMessage("Could not establish file template loader for directory: target/test-output/freemarker-mojo/setTemplateLoaderException/template");
-  }
-  
-  @Test
-  public void execute_loadFreemarkerPropertiesTest(
-      @Mocked MavenSession session,
-      @Mocked MavenProject project,
-      @Mocked MojoExecution mojoExecution,
-      @Mocked Configuration config) throws Exception {
-    
-    FreeMarkerMojo mojo = new FreeMarkerMojo();
-
-    File sourceDirectory = new File("src/test/data/freemarker-mojo");
-    File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "loadFreemarkerProperties");
-
-    Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
-    Deencapsulation.setField(mojo, "sourceDirectory", sourceDirectory);
-    Deencapsulation.setField(mojo, "templateDirectory", new File( sourceDirectory, "template"));
-    Deencapsulation.setField(mojo, "generatorDirectory", new File( sourceDirectory, "data"));
-    Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
-    Deencapsulation.setField(mojo, "mojo", mojoExecution);
-    Deencapsulation.setField(mojo, "session", session);
-
-    mojo.execute();
-    
-    new Verifications() {{
-      Properties properties;
-      
-      config.setSettings(properties = withCapture()); times = 1;
-      
-      assertEquals("T,F", properties.getProperty("boolean_format"));
-    }};
-  }
-  
-  @Test
-  public void execute_loadFreemarkerPropertiesExceptionTest(
-      @Mocked MavenSession session,
-      @Mocked MavenProject project,
-      @Mocked MojoExecution mojoExecution,
-      @Mocked FactoryUtil factoryUtil,
-      @Mocked Configuration config) throws Exception {
-    
-    new Expectations(FactoryUtil.class) {{
-      FactoryUtil.createFileInputStream((File) any); result = new RuntimeException("test exception");
-    }};
-    
-    FreeMarkerMojo mojo = new FreeMarkerMojo();
-
-    File sourceDirectory = new File("src/test/data/freemarker-mojo");
-    File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "loadFreemarkerPropertiesExceptionTest");
-
-    Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
-    Deencapsulation.setField(mojo, "sourceDirectory", sourceDirectory);
-    Deencapsulation.setField(mojo, "templateDirectory", new File( sourceDirectory, "template"));
-    Deencapsulation.setField(mojo, "generatorDirectory", new File( sourceDirectory, "data"));
-    Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
-    Deencapsulation.setField(mojo, "mojo", mojoExecution);
-    Deencapsulation.setField(mojo, "session", session);
-
-    System.out.println("==== before mojo execute");
-    try {
-    assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
-      mojo.execute();
-    }).withMessage("Failed to load src/test/data/freemarker-mojo/freemarker.properties");
-    } catch ( Throwable t) {
-      t.printStackTrace();
+
+    @Test
+    public void execute_loadFreemarkerPropertiesTest(
+            @Mocked MavenSession session,
+            @Mocked MavenProject project,
+            @Mocked MojoExecution mojoExecution,
+            @Mocked Configuration config) throws Exception {
+
+        FreeMarkerMojo mojo = new FreeMarkerMojo();
+
+        File sourceDirectory = new File("src/test/data/freemarker-mojo");
+        File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "loadFreemarkerProperties");
+
+        Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
+        Deencapsulation.setField(mojo, "sourceDirectory", sourceDirectory);
+        Deencapsulation.setField(mojo, "templateDirectory", new File(sourceDirectory, "template"));
+        Deencapsulation.setField(mojo, "generatorDirectory", new File(sourceDirectory, "data"));
+        Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
+        Deencapsulation.setField(mojo, "mojo", mojoExecution);
+        Deencapsulation.setField(mojo, "session", session);
+
+        mojo.execute();
+
+        new Verifications() {{
+            Properties properties;
+
+            config.setSettings(properties = withCapture());
+            times = 1;
+
+            assertEquals("T,F", properties.getProperty("boolean_format"));
+        }};
+    }
+
+    @Test
+    public void execute_loadFreemarkerPropertiesExceptionTest(
+            @Mocked MavenSession session,
+            @Mocked MavenProject project,
+            @Mocked MojoExecution mojoExecution,
+            @Mocked FactoryUtil factoryUtil,
+            @Mocked Configuration config) throws Exception {
+
+        new Expectations(FactoryUtil.class) {{
+            FactoryUtil.createFileInputStream((File) any);
+            result = new RuntimeException("test exception");
+        }};
+
+        FreeMarkerMojo mojo = new FreeMarkerMojo();
+
+        File sourceDirectory = new File("src/test/data/freemarker-mojo");
+        File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "loadFreemarkerPropertiesExceptionTest");
+
+        Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
+        Deencapsulation.setField(mojo, "sourceDirectory", sourceDirectory);
+        Deencapsulation.setField(mojo, "templateDirectory", new File(sourceDirectory, "template"));
+        Deencapsulation.setField(mojo, "generatorDirectory", new File(sourceDirectory, "data"));
+        Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
+        Deencapsulation.setField(mojo, "mojo", mojoExecution);
+        Deencapsulation.setField(mojo, "session", session);
+
+        System.out.println("==== before mojo execute");
+        try {
+            assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
+                mojo.execute();
+            }).withMessage("Failed to load src/test/data/freemarker-mojo/freemarker.properties");
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
     }
-  }
-
-  @Test
-  public void execute_setSettingsExceptionTest(
-      @Mocked MavenSession session,
-      @Mocked MavenProject project,
-      @Mocked MojoExecution mojoExecution,
-      @Mocked Configuration config) throws Exception {
-    
-    new Expectations() {{
-      config.setSettings((Properties) any); result = new RuntimeException("test exception");
-    }};
-    
-    FreeMarkerMojo mojo = new FreeMarkerMojo();
-
-    File sourceDirectory = new File("src/test/data/freemarker-mojo");
-    File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "loadFreemarkerProperties");
-
-    Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
-    Deencapsulation.setField(mojo, "sourceDirectory", sourceDirectory);
-    Deencapsulation.setField(mojo, "templateDirectory", new File( sourceDirectory, "template"));
-    Deencapsulation.setField(mojo, "generatorDirectory", new File( sourceDirectory, "data"));
-    Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
-    Deencapsulation.setField(mojo, "mojo", mojoExecution);
-    Deencapsulation.setField(mojo, "session", session);
-
-    assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
-      mojo.execute();
-    }).withMessage("Invalid setting(s) in src/test/data/freemarker-mojo/freemarker.properties");
-  }
-  
+
+    @Test
+    public void execute_setSettingsExceptionTest(
+            @Mocked MavenSession session,
+            @Mocked MavenProject project,
+            @Mocked MojoExecution mojoExecution,
+            @Mocked Configuration config) throws Exception {
+
+        new Expectations() {{
+            config.setSettings((Properties) any);
+            result = new RuntimeException("test exception");
+        }};
+
+        FreeMarkerMojo mojo = new FreeMarkerMojo();
+
+        File sourceDirectory = new File("src/test/data/freemarker-mojo");
+        File testCaseOutputDir = new File(TEST_OUTPUT_DIR, "loadFreemarkerProperties");
+
+        Deencapsulation.setField(mojo, "freeMarkerVersion", FREEMARKER_VERSION);
+        Deencapsulation.setField(mojo, "sourceDirectory", sourceDirectory);
+        Deencapsulation.setField(mojo, "templateDirectory", new File(sourceDirectory, "template"));
+        Deencapsulation.setField(mojo, "generatorDirectory", new File(sourceDirectory, "data"));
+        Deencapsulation.setField(mojo, "outputDirectory", new File(testCaseOutputDir, "generated-files"));
+        Deencapsulation.setField(mojo, "mojo", mojoExecution);
+        Deencapsulation.setField(mojo, "session", session);
+
+        assertThatExceptionOfType(MojoExecutionException.class).isThrownBy(() -> {
+            mojo.execute();
+        }).withMessage("Invalid setting(s) in src/test/data/freemarker-mojo/freemarker.properties");
+    }
+
 }
diff --git a/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/GeneratingFileVisitorTest.java b/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/GeneratingFileVisitorTest.java
index 0d83612..d446120 100644
--- a/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/GeneratingFileVisitorTest.java
+++ b/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/GeneratingFileVisitorTest.java
@@ -19,7 +19,16 @@
 
 package org.apache.freemarker.generator.maven;
 
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import freemarker.cache.FileTemplateLoader;
+import freemarker.template.Configuration;
+import mockit.Expectations;
+import mockit.Mocked;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.project.MavenProject;
+import org.junit.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
 
 import java.io.File;
 import java.io.IOException;
@@ -28,157 +37,170 @@ import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
 
-import org.apache.freemarker.generator.maven.GeneratingFileVisitor;
-import org.apache.freemarker.generator.maven.JsonPropertiesProvider;
-import org.apache.freemarker.generator.maven.OutputGeneratorPropertiesProvider;
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.project.MavenProject;
-import org.junit.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import freemarker.cache.FileTemplateLoader;
-import freemarker.template.Configuration;
-import mockit.Expectations;
-import mockit.Mocked;
+import static org.assertj.core.api.Assertions.*;
 
 public class GeneratingFileVisitorTest extends Assert {
 
-  private static File testDir = new File("src/test/data/generating-file-visitor");
-  private static File dataDir = new File(testDir, "data");
-  private static File templateDir = new File(testDir, "template");
-  private static File outputDir = new File("target/test-output/generating-file-visitor");
-  private static Map<String, OutputGeneratorPropertiesProvider> builders = new HashMap<>();
-  private Configuration config;
-  private Properties pomProperties = new Properties();
-  
-  @BeforeClass
-  public static void beforeClass() throws IOException {
-  	 builders.put(".json", JsonPropertiesProvider.create(dataDir,templateDir,outputDir));
-    // Clean output dir before each run.
-    File outputDir = new File("target/test-output/generating-file-visitor");
-    if (outputDir.exists()) {
-      // Recursively delete output from previous run.
-      Files.walk(outputDir.toPath())
-       .sorted(Comparator.reverseOrder())
-       .map(Path::toFile)
-       .forEach(File::delete);
+    private static File testDir = new File("src/test/data/generating-file-visitor");
+    private static File dataDir = new File(testDir, "data");
+    private static File templateDir = new File(testDir, "template");
+    private static File outputDir = new File("target/test-output/generating-file-visitor");
+    private static Map<String, OutputGeneratorPropertiesProvider> builders = new HashMap<>();
+    private Configuration config;
+    private Properties pomProperties = new Properties();
+
+    @BeforeClass
+    public static void beforeClass() throws IOException {
+        builders.put(".json", JsonPropertiesProvider.create(dataDir, templateDir, outputDir));
+        // Clean output dir before each run.
+        File outputDir = new File("target/test-output/generating-file-visitor");
+        if (outputDir.exists()) {
+            // Recursively delete output from previous run.
+            Files.walk(outputDir.toPath())
+                    .sorted(Comparator.reverseOrder())
+                    .map(Path::toFile)
+                    .forEach(File::delete);
+        }
     }
-  }
-
-  @BeforeMethod
-  public void before() throws IOException {
-    if (!testDir.isDirectory()) {
-      throw new RuntimeException("Can't find required test data directory. "
-          + "If running test outside of maven, make sure working directory is the project directory. "
-          + "Looking for: " + testDir);
+
+    @BeforeMethod
+    public void before() throws IOException {
+        if (!testDir.isDirectory()) {
+            throw new RuntimeException("Can't find required test data directory. "
+                    + "If running test outside of maven, make sure working directory is the project directory. "
+                    + "Looking for: " + testDir);
+        }
+
+        config = new Configuration(Configuration.VERSION_2_3_23);
+        config.setDefaultEncoding("UTF-8");
+        config.setTemplateLoader(new FileTemplateLoader(templateDir));
+        pomProperties.put("pomVar", "pom value");
     }
 
-    config = new Configuration(Configuration.VERSION_2_3_23);
-    config.setDefaultEncoding("UTF-8");
-    config.setTemplateLoader(new FileTemplateLoader(templateDir));
-    pomProperties.put("pomVar", "pom value");
-  }
-  
-  @Test
-  public void functionalHappyPathTestNoDataModel(
-      @Mocked MavenSession session, 
-      @Mocked MavenProject project,
-      @Mocked File mockFile,
-      @Mocked BasicFileAttributes attrs) throws IOException {
-    List<MavenProject> projects = new ArrayList<>();
-    projects.add(project);
-    new Expectations(session, project, mockFile) {{
-      session.getCurrentProject(); result = project;
-      session.getAllProjects(); result = projects;
-      project.getProperties(); result = pomProperties;
-      attrs.isRegularFile(); result = true;
-      project.getFile(); result = mockFile;
-      mockFile.lastModified(); result = 10;
-    }};
-    
-    File file = new File(dataDir, "mydir/success-test-2.txt.json");
-    GeneratingFileVisitor gfv = GeneratingFileVisitor.create(config, session, builders);
-    assertEquals(FileVisitResult.CONTINUE, gfv.visitFile(file.toPath(), attrs));
-    
-    File outputFile = new File(outputDir, "mydir/success-test-2.txt");
-    assertTrue(outputFile.isFile());
-    List<String> lines = Files.readAllLines(outputFile.toPath(), StandardCharsets.UTF_8);
-    assertEquals(1, lines.size());
-    assertEquals("This is a test freemarker template. Test pom data: 'pom value'.", lines.get(0));
-  }
-
-  @Test
-  public void functionalHappyPathTest(
-      @Mocked MavenSession session,
-      @Mocked MavenProject project,
-      @Mocked File mockFile,
-      @Mocked BasicFileAttributes attrs) throws IOException {
-    List<MavenProject> projects = new ArrayList<>();
-    projects.add(project);
-    new Expectations(session, project, mockFile) {{
-      session.getCurrentProject(); result = project;
-      session.getAllProjects(); result = projects;
-      project.getProperties(); result = pomProperties;
-      attrs.isRegularFile(); result = true;
-      project.getFile(); result = mockFile;
-      mockFile.lastModified(); result = 10;
-    }};
-
-    File file = new File(dataDir, "mydir/success-test.txt.json");
-    GeneratingFileVisitor gfv = GeneratingFileVisitor.create(config, session, builders);
-    assertEquals(FileVisitResult.CONTINUE, gfv.visitFile(file.toPath(), attrs));
-
-    File outputFile = new File(outputDir, "mydir/success-test.txt");
-    assertTrue(outputFile.isFile());
-    List<String> lines = Files.readAllLines(outputFile.toPath(), StandardCharsets.UTF_8);
-    assertEquals(1, lines.size());
-    assertEquals("This is a test freemarker template. Test json data: 'test value'. Test pom data: 'pom value'.", lines.get(0));
-  }
-
-  @Test
-  public void visitFile_badExtensionTest(
-      @Mocked MavenSession session,
-      @Mocked MavenProject project,
-      @Mocked File mockFile,
-      @Mocked BasicFileAttributes attrs) throws IOException {
-    List<MavenProject> projects = new ArrayList<>();
-    projects.add(project);
-    new Expectations(session, project, mockFile) {{
-      attrs.isRegularFile(); result = true;
-      session.getAllProjects(); result = projects;
-      project.getFile(); result = mockFile;
-      mockFile.lastModified(); result = 10;
-    }};
-    // Test file without .json suffix.
-    File file = new File(dataDir, "mydir/bad-extension-test.txt");
-    GeneratingFileVisitor gfv = GeneratingFileVisitor.create(config, session, builders);
-    assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
-      gfv.visitFile(file.toPath(), attrs);
-    }).withMessage("Unknown file extension: " + file.toPath());
-  }
-
-  @Test 
-  public void visitFile_notRegularFileTest(@Mocked MavenSession session,
-                                           @Mocked MavenProject project,
-                                           @Mocked BasicFileAttributes attrs,
-                                           @Mocked File mockFile
-                                           ) {
-    List<MavenProject> projects = new ArrayList<>();
-    projects.add(project);
-    new Expectations(session, project, mockFile) {{
-      attrs.isRegularFile(); result = false;
-      session.getAllProjects(); result = projects;
-      project.getFile(); result = mockFile;
-      mockFile.lastModified(); result = 10;
-    }};
-    // FYI: if you change above result to true, test will fail trying to read the 'mydir' directory
-    // as a json file.
-    File dir = new File(dataDir, "mydir");
-    GeneratingFileVisitor gfv = GeneratingFileVisitor.create(config, session, builders);
-    assertEquals(FileVisitResult.CONTINUE, gfv.visitFile(dir.toPath(), attrs));
-  }
+    @Test
+    public void functionalHappyPathTestNoDataModel(
+            @Mocked MavenSession session,
+            @Mocked MavenProject project,
+            @Mocked File mockFile,
+            @Mocked BasicFileAttributes attrs) throws IOException {
+        List<MavenProject> projects = new ArrayList<>();
+        projects.add(project);
+        new Expectations(session, project, mockFile) {{
+            session.getCurrentProject();
+            result = project;
+            session.getAllProjects();
+            result = projects;
+            project.getProperties();
+            result = pomProperties;
+            attrs.isRegularFile();
+            result = true;
+            project.getFile();
+            result = mockFile;
+            mockFile.lastModified();
+            result = 10;
+        }};
+
+        File file = new File(dataDir, "mydir/success-test-2.txt.json");
+        GeneratingFileVisitor gfv = GeneratingFileVisitor.create(config, session, builders);
+        assertEquals(FileVisitResult.CONTINUE, gfv.visitFile(file.toPath(), attrs));
+
+        File outputFile = new File(outputDir, "mydir/success-test-2.txt");
+        assertTrue(outputFile.isFile());
+        List<String> lines = Files.readAllLines(outputFile.toPath(), StandardCharsets.UTF_8);
+        assertEquals(1, lines.size());
+        assertEquals("This is a test freemarker template. Test pom data: 'pom value'.", lines.get(0));
+    }
+
+    @Test
+    public void functionalHappyPathTest(
+            @Mocked MavenSession session,
+            @Mocked MavenProject project,
+            @Mocked File mockFile,
+            @Mocked BasicFileAttributes attrs) throws IOException {
+        List<MavenProject> projects = new ArrayList<>();
+        projects.add(project);
+        new Expectations(session, project, mockFile) {{
+            session.getCurrentProject();
+            result = project;
+            session.getAllProjects();
+            result = projects;
+            project.getProperties();
+            result = pomProperties;
+            attrs.isRegularFile();
+            result = true;
+            project.getFile();
+            result = mockFile;
+            mockFile.lastModified();
+            result = 10;
+        }};
+
+        File file = new File(dataDir, "mydir/success-test.txt.json");
+        GeneratingFileVisitor gfv = GeneratingFileVisitor.create(config, session, builders);
+        assertEquals(FileVisitResult.CONTINUE, gfv.visitFile(file.toPath(), attrs));
+
+        File outputFile = new File(outputDir, "mydir/success-test.txt");
+        assertTrue(outputFile.isFile());
+        List<String> lines = Files.readAllLines(outputFile.toPath(), StandardCharsets.UTF_8);
+        assertEquals(1, lines.size());
+        assertEquals("This is a test freemarker template. Test json data: 'test value'. Test pom data: 'pom value'.", lines
+                .get(0));
+    }
+
+    @Test
+    public void visitFile_badExtensionTest(
+            @Mocked MavenSession session,
+            @Mocked MavenProject project,
+            @Mocked File mockFile,
+            @Mocked BasicFileAttributes attrs) throws IOException {
+        List<MavenProject> projects = new ArrayList<>();
+        projects.add(project);
+        new Expectations(session, project, mockFile) {{
+            attrs.isRegularFile();
+            result = true;
+            session.getAllProjects();
+            result = projects;
+            project.getFile();
+            result = mockFile;
+            mockFile.lastModified();
+            result = 10;
+        }};
+        // Test file without .json suffix.
+        File file = new File(dataDir, "mydir/bad-extension-test.txt");
+        GeneratingFileVisitor gfv = GeneratingFileVisitor.create(config, session, builders);
+        assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
+            gfv.visitFile(file.toPath(), attrs);
+        }).withMessage("Unknown file extension: " + file.toPath());
+    }
+
+    @Test
+    public void visitFile_notRegularFileTest(@Mocked MavenSession session,
+                                             @Mocked MavenProject project,
+                                             @Mocked BasicFileAttributes attrs,
+                                             @Mocked File mockFile
+    ) {
+        List<MavenProject> projects = new ArrayList<>();
+        projects.add(project);
+        new Expectations(session, project, mockFile) {{
+            attrs.isRegularFile();
+            result = false;
+            session.getAllProjects();
+            result = projects;
+            project.getFile();
+            result = mockFile;
+            mockFile.lastModified();
+            result = 10;
+        }};
+        // FYI: if you change above result to true, test will fail trying to read the 'mydir' directory
+        // as a json file.
+        File dir = new File(dataDir, "mydir");
+        GeneratingFileVisitor gfv = GeneratingFileVisitor.create(config, session, builders);
+        assertEquals(FileVisitResult.CONTINUE, gfv.visitFile(dir.toPath(), attrs));
+    }
 }
diff --git a/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/JsonPropertiesProviderTest.java b/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/JsonPropertiesProviderTest.java
index 2bd842e..88d8fc6 100644
--- a/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/JsonPropertiesProviderTest.java
+++ b/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/JsonPropertiesProviderTest.java
@@ -24,8 +24,6 @@ import com.google.gson.stream.JsonReader;
 import mockit.Expectations;
 import mockit.Mocked;
 import mockit.Verifications;
-import org.apache.freemarker.generator.maven.JsonPropertiesProvider;
-import org.apache.freemarker.generator.maven.OutputGenerator;
 import org.testng.annotations.Test;
 
 import java.io.File;
@@ -34,90 +32,93 @@ import java.nio.file.Path;
 import java.util.HashMap;
 import java.util.Map;
 
-import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
+import static org.assertj.core.api.AssertionsForClassTypes.*;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
 
 public class JsonPropertiesProviderTest {
-	private File testDir = new File("src/test/data/generating-file-visitor");
-	private File dataDir = new File(testDir, "data");
-	private File templateDir = new File(testDir, "template");
-	private File outputDir = new File("target/test-output/generating-file-visitor");
+    private File testDir = new File("src/test/data/generating-file-visitor");
+    private File dataDir = new File(testDir, "data");
+    private File templateDir = new File(testDir, "template");
+    private File outputDir = new File("target/test-output/generating-file-visitor");
 
-	@Test
-	public void testSuccess(@Mocked OutputGenerator.OutputGeneratorBuilder builder) {
-		Path path = dataDir.toPath().resolve("mydir/success-test.txt.json");
-		Path expectedTemplateLocation = templateDir.toPath().resolve("test.ftl");
-		Path expectedOutputLocation = outputDir.toPath().resolve("mydir/success-test.txt");
-		Map<String,Object> expectedMap = new HashMap<String,Object>(4);
-		expectedMap.put("testVar", "test value");
-		JsonPropertiesProvider toTest = JsonPropertiesProvider.create(dataDir, templateDir, outputDir);
-		toTest.providePropertiesFromFile(path, builder);
-		new Verifications(){{
-			Path templateLocation;
-			builder.addTemplateLocation(templateLocation = withCapture());
-			Path outputLocation;
-			builder.addOutputLocation(outputLocation = withCapture());
-			Map<String,Object> actualMap;
-			builder.addDataModel(actualMap = withCapture());
+    @Test
+    public void testSuccess(@Mocked OutputGenerator.OutputGeneratorBuilder builder) {
+        Path path = dataDir.toPath().resolve("mydir/success-test.txt.json");
+        Path expectedTemplateLocation = templateDir.toPath().resolve("test.ftl");
+        Path expectedOutputLocation = outputDir.toPath().resolve("mydir/success-test.txt");
+        Map<String, Object> expectedMap = new HashMap<>(4);
+        expectedMap.put("testVar", "test value");
+        JsonPropertiesProvider toTest = JsonPropertiesProvider.create(dataDir, templateDir, outputDir);
+        toTest.providePropertiesFromFile(path, builder);
+        new Verifications() {{
+            Path templateLocation;
+            builder.addTemplateLocation(templateLocation = withCapture());
+            Path outputLocation;
+            builder.addOutputLocation(outputLocation = withCapture());
+            Map<String, Object> actualMap;
+            builder.addDataModel(actualMap = withCapture());
 
-			assertEquals(expectedTemplateLocation, templateLocation);
-			assertEquals(expectedOutputLocation, outputLocation);
-			assertArrayEquals(expectedMap.entrySet().toArray(), actualMap.entrySet().toArray());
-		}};
-	}
+            assertEquals(expectedTemplateLocation, templateLocation);
+            assertEquals(expectedOutputLocation, outputLocation);
+            assertArrayEquals(expectedMap.entrySet().toArray(), actualMap.entrySet().toArray());
+        }};
+    }
 
-	@Test
-	public void testSuccessNoDataModel(@Mocked OutputGenerator.OutputGeneratorBuilder builder) {
-		Path path = dataDir.toPath().resolve("mydir/success-test-2.txt.json");
-		Path expectedTemplateLocation = templateDir.toPath().resolve("test-pom-only.ftl");
-		Path expectedOutputLocation = outputDir.toPath().resolve("mydir/success-test-2.txt");
-		Map<String,Object> expectedMap = new HashMap<String,Object>(4);
-		JsonPropertiesProvider toTest = JsonPropertiesProvider.create(dataDir, templateDir, outputDir);
-		toTest.providePropertiesFromFile(path, builder);
-		new Verifications(){{
-			Path templateLocation;
-			builder.addTemplateLocation(templateLocation = withCapture());
-			Path outputLocation;
-			builder.addOutputLocation(outputLocation = withCapture());
-			Map<String,Object> actualMap;
-			builder.addDataModel(actualMap = withCapture());
+    @Test
+    public void testSuccessNoDataModel(@Mocked OutputGenerator.OutputGeneratorBuilder builder) {
+        Path path = dataDir.toPath().resolve("mydir/success-test-2.txt.json");
+        Path expectedTemplateLocation = templateDir.toPath().resolve("test-pom-only.ftl");
+        Path expectedOutputLocation = outputDir.toPath().resolve("mydir/success-test-2.txt");
+        Map<String, Object> expectedMap = new HashMap<>(4);
+        JsonPropertiesProvider toTest = JsonPropertiesProvider.create(dataDir, templateDir, outputDir);
+        toTest.providePropertiesFromFile(path, builder);
+        new Verifications() {{
+            Path templateLocation;
+            builder.addTemplateLocation(templateLocation = withCapture());
+            Path outputLocation;
+            builder.addOutputLocation(outputLocation = withCapture());
+            Map<String, Object> actualMap;
+            builder.addDataModel(actualMap = withCapture());
 
-			assertEquals(expectedTemplateLocation, templateLocation);
-			assertEquals(expectedOutputLocation, outputLocation);
-			assertArrayEquals(expectedMap.entrySet().toArray(), actualMap.entrySet().toArray());
-		}};
-	}
+            assertEquals(expectedTemplateLocation, templateLocation);
+            assertEquals(expectedOutputLocation, outputLocation);
+            assertArrayEquals(expectedMap.entrySet().toArray(), actualMap.entrySet().toArray());
+        }};
+    }
 
-	@Test
-	public void testParsingException(@Mocked OutputGenerator.OutputGeneratorBuilder builder, @Mocked Gson gson) {
-		Path path = dataDir.toPath().resolve("mydir/success-test.txt.json");
-		new Expectations() {{
-			gson.fromJson((JsonReader) any, (Type) any); result = new RuntimeException("test exception");
-		}};
-		JsonPropertiesProvider toTest = JsonPropertiesProvider.create(dataDir, templateDir, outputDir);
+    @Test
+    public void testParsingException(@Mocked OutputGenerator.OutputGeneratorBuilder builder, @Mocked Gson gson) {
+        Path path = dataDir.toPath().resolve("mydir/success-test.txt.json");
+        new Expectations() {{
+            gson.fromJson((JsonReader) any, (Type) any);
+            result = new RuntimeException("test exception");
+        }};
+        JsonPropertiesProvider toTest = JsonPropertiesProvider.create(dataDir, templateDir, outputDir);
 
-		assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
-			toTest.providePropertiesFromFile(path, builder);
-		}).withMessage("Could not parse json data file: src/test/data/generating-file-visitor/data/mydir/success-test.txt.json");
-	}
+        assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
+            toTest.providePropertiesFromFile(path, builder);
+        })
+                .withMessage("Could not parse json data file: src/test/data/generating-file-visitor/data/mydir/success-test.txt.json");
+    }
 
-	@Test
-	public void testMissingTemplateName(@Mocked OutputGenerator.OutputGeneratorBuilder builder) {
-		Path path = dataDir.toPath().resolve("mydir/missing-template-name.txt.json");
-		JsonPropertiesProvider toTest = JsonPropertiesProvider.create(dataDir, templateDir, outputDir);
+    @Test
+    public void testMissingTemplateName(@Mocked OutputGenerator.OutputGeneratorBuilder builder) {
+        Path path = dataDir.toPath().resolve("mydir/missing-template-name.txt.json");
+        JsonPropertiesProvider toTest = JsonPropertiesProvider.create(dataDir, templateDir, outputDir);
 
-		assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
-			toTest.providePropertiesFromFile(path, builder);
-		}).withMessage("Require json data property not found: templateName");
-	}
+        assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
+            toTest.providePropertiesFromFile(path, builder);
+        }).withMessage("Require json data property not found: templateName");
+    }
 
-	@Test
-	public void testBadPath(@Mocked OutputGenerator.OutputGeneratorBuilder builder) {
-		Path path = testDir.toPath().resolve("badPath/success-test.txt.json");
-		JsonPropertiesProvider toTest = JsonPropertiesProvider.create(dataDir, templateDir, outputDir);
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			toTest.providePropertiesFromFile(path, builder);
-		}).withMessage("visitFile() given file not in sourceDirectory: src/test/data/generating-file-visitor/badPath/success-test.txt.json");
-	}
+    @Test
+    public void testBadPath(@Mocked OutputGenerator.OutputGeneratorBuilder builder) {
+        Path path = testDir.toPath().resolve("badPath/success-test.txt.json");
+        JsonPropertiesProvider toTest = JsonPropertiesProvider.create(dataDir, templateDir, outputDir);
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            toTest.providePropertiesFromFile(path, builder);
+        })
+                .withMessage("visitFile() given file not in sourceDirectory: src/test/data/generating-file-visitor/badPath/success-test.txt.json");
+    }
 }
diff --git a/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/OutputGeneratorTest.java b/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/OutputGeneratorTest.java
index 4a34851..43956a8 100644
--- a/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/OutputGeneratorTest.java
+++ b/freemarker-generator-maven-plugin/src/test/java/org/apache/freemarker/generator/maven/OutputGeneratorTest.java
@@ -23,275 +23,283 @@ import freemarker.cache.FileTemplateLoader;
 import freemarker.template.Configuration;
 import mockit.Expectations;
 import mockit.Mocked;
-import org.apache.freemarker.generator.maven.FactoryUtil;
-import org.apache.freemarker.generator.maven.OutputGenerator;
-import org.assertj.core.api.Assertions;
+import org.assertj.core.api.*;
 import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
 import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
 
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.*;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 import static junit.framework.Assert.assertEquals;
-import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
+import static org.assertj.core.api.AssertionsForClassTypes.*;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertTrue;
 
 public class OutputGeneratorTest {
 
-	private File testDir = new File("src/test/data/generating-file-visitor");
-	private File dataDir = new File(testDir, "data");
-	private File templateDir = new File(testDir, "template");
-	private File outputDir = new File("target/test-output/generating-file-visitor");
-	private Configuration config;
-	private Map<String, Object> dataModel = new HashMap<String,Object>();
-
-	@BeforeMethod
-	public void setupDataModel() {
-		dataModel.clear();
-		dataModel.put("testVar", "test value");
-		dataModel.put("pomProperties", new HashMap<String,String>());
-		((Map<String,String>)dataModel.get("pomProperties")).put("pomVar", "pom value");
-	}
-
-	@BeforeClass
-	public static void cleanFields() throws IOException {
-		// Clean output dir before each run.
-		File outputDir = new File("target/test-output/generating-file-visitor");
-		if (outputDir.exists()) {
-			// Recursively delete output from previous run.
-			Files.walk(outputDir.toPath())
-				 .sorted(Comparator.reverseOrder())
-				 .map(Path::toFile)
-				 .forEach(File::delete);
-		}
-	}
-
-	@BeforeMethod
-	public void before() throws IOException {
-		if (!testDir.isDirectory()) {
-			throw new RuntimeException("Can't find required test data directory. "
-				 + "If running test outside of maven, make sure working directory is the project directory. "
-				 + "Looking for: " + testDir);
-		}
-
-		config = new Configuration(Configuration.VERSION_2_3_23);
-		config.setDefaultEncoding("UTF-8");
-		config.setTemplateLoader(new FileTemplateLoader(templateDir));
-	}
-
-	@Test
-	public void createTest() {
-		OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			builder.create();
-		}).withMessage("Must set the pomModifiedTimestamp");
-
-		builder.addPomLastModifiedTimestamp(0);
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			builder.create();
-		}).withMessage("Must set a non-null generatorLocation");
-
-		File file = new File(dataDir, "mydir/success-test.txt.json");
-		builder.addGeneratorLocation(file.toPath());
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			builder.create();
-		}).withMessage("Must set a non-null templateLocation");
-
-		File templateFile = new File(templateDir, "test.ftl");
-		builder.addTemplateLocation(templateFile.toPath());
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			builder.create();
-		}).withMessage("Must set a non-null outputLocation");
-
-		File outputFile = new File(outputDir, "mydir/success-test.txt");
-		builder.addOutputLocation(outputFile.toPath());
-
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			builder.create();
-		}).withMessage("Must set a non-null dataModel");
-
-		builder.addDataModel(dataModel);
-		OutputGenerator generator = builder.create();
-
-		assertEquals(0, generator.pomModifiedTimestamp);
-		assertEquals(file.toPath(), generator.generatorLocation);
-		assertEquals(templateFile.toPath(), generator.templateLocation);
-		assertEquals(outputFile.toPath(), generator.outputLocation);
-		assertEquals(dataModel.size(), generator.dataModel.size());
-		assertArrayEquals(dataModel.entrySet().toArray(), generator.dataModel.entrySet().toArray());
-	}
-
-	@Test
-	public void addToDataModelTest() {
-		OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			builder.create();
-		}).withMessage("Must set the pomModifiedTimestamp");
-
-		builder.addPomLastModifiedTimestamp(0);
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			builder.create();
-		}).withMessage("Must set a non-null generatorLocation");
-
-		File file = new File(dataDir, "mydir/success-test.txt.json");
-		builder.addGeneratorLocation(file.toPath());
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			builder.create();
-		}).withMessage("Must set a non-null templateLocation");
-
-		File templateFile = new File(templateDir, "test.ftl");
-		builder.addTemplateLocation(templateFile.toPath());
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			builder.create();
-		}).withMessage("Must set a non-null outputLocation");
-
-		File outputFile = new File(outputDir, "mydir/success-test.txt");
-		builder.addOutputLocation(outputFile.toPath());
-
-		assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
-			builder.create();
-		}).withMessage("Must set a non-null dataModel");
-
-		builder.addToDataModel("testVar", "testVal");
-		OutputGenerator generator = builder.create();
-
-		assertEquals(1, generator.dataModel.size());
-		assertEquals( "testVal", generator.dataModel.get("testVar"));
-
-		builder.addDataModel(dataModel);
-		builder.addToDataModel("testVar2", "testVal2");
-
-		generator = builder.create();
-
-		assertEquals(3, generator.dataModel.size());
-		assertEquals( "test value", generator.dataModel.get("testVar"));
-		assertEquals( "testVal2", generator.dataModel.get("testVar2"));
-	}
-
-	@Test
-	public void generate_SuccessTest()
-		  throws IOException {
-		OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
-		builder.addPomLastModifiedTimestamp(0);
-		File file = new File(dataDir, "mydir/success-test.txt.json");
-		builder.addGeneratorLocation(file.toPath());
-		File outputFile = new File(outputDir, "mydir/success-test.txt");
-		builder.addOutputLocation(outputFile.toPath());
-		File templateFile = new File(templateDir, "test.ftl");
-		builder.addTemplateLocation(templateFile.toPath());
-		builder.addDataModel(dataModel);
-		OutputGenerator generator = builder.create();
-		generator.generate(config);
-
-		assertTrue(outputFile.isFile());
-		List<String> lines = Files.readAllLines(outputFile.toPath(), StandardCharsets.UTF_8);
-		assertEquals(1, lines.size());
-		assertEquals("This is a test freemarker template. Test json data: 'test value'. Test pom data: 'pom value'.", lines.get(0));
-
-		// Process same file again, should not regenerate file.
-		long lastMod = outputFile.lastModified();
-		generator.generate(config);
-		assertEquals(lastMod, outputFile.lastModified());
-
-		// Set mod time to before json file.
-		lastMod = file.lastModified() - 1000; // File system may only keep 1 second precision.
-		outputFile.setLastModified(lastMod);
-		generator.generate(config);
-		assertTrue(lastMod < outputFile.lastModified());
-
-		// Set mod time to before template file.
-		lastMod = templateFile.lastModified() - 1000; // File system may only keep 1 second precision.
-		outputFile.setLastModified(lastMod);
-		generator.generate(config);
-		assertTrue(lastMod < outputFile.lastModified());
-	}
-
-	@Test
-	public void generate_badTemplateNameTest(){
-		OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
-		builder.addPomLastModifiedTimestamp(0);
-		File file = new File(dataDir, "mydir/bad-template-name.txt.json");
-		builder.addGeneratorLocation(file.toPath());
-		File outputFile = new File(outputDir, "mydir/bad-template-name.txt");
-		builder.addOutputLocation(outputFile.toPath());
-		File templateFile = new File(templateDir, "missing.ftl"); //this doesn't exist
-		builder.addTemplateLocation(templateFile.toPath());
-		builder.addDataModel(dataModel);
-		OutputGenerator generator = builder.create();
-		Assertions.assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
-			generator.generate(config);
-		}).withMessage("Could not read template: missing.ftl");
-	}
-
-	@Test
-	public void generate_missingVarTest() {
-		OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
-		builder.addPomLastModifiedTimestamp(0);
-		File file = new File(dataDir, "mydir/missing-var-test.txt.json");
-		builder.addGeneratorLocation(file.toPath());
-		File outputFile = new File(outputDir, "mydir/missing-var-test.txt");
-		builder.addOutputLocation(outputFile.toPath());
-		File templateFile = new File(templateDir, "test.ftl"); //this is missing a
-		builder.addTemplateLocation(templateFile.toPath());
-		dataModel.remove("testVar");
-		builder.addDataModel(dataModel);
-		OutputGenerator generator = builder.create();
-		Assertions.assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
-			generator.generate(config);
-		}).withMessage("Could not process template associated with data file: src/test/data/generating-file-visitor/data/mydir/missing-var-test.txt.json");
-	}
-
-	@Test
-	public void generate_badParentTest() throws IOException {
-		OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
-		builder.addPomLastModifiedTimestamp(0);
-		File file = new File(dataDir, "badParent/bad-parent-test.txt.json");
-		builder.addGeneratorLocation(file.toPath());
-		File outputFile = new File(outputDir, "badParent/bad-parent-test.txt");
-		builder.addOutputLocation(outputFile.toPath());
-		File templateFile = new File(templateDir, "test.ftl"); //this is missing a
-		builder.addTemplateLocation(templateFile.toPath());
-		builder.addDataModel(dataModel);
-		OutputGenerator generator = builder.create();
-		outputDir.mkdirs();
-		outputFile.getParentFile().createNewFile();
-
-		Assertions.assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
-			generator.generate(config);
-		}).withMessage("Parent directory of output file is a file: " + outputFile.getParentFile().getAbsolutePath());
-	}
-
-	@Test
-	public void generate_cantCreateOutputFileParentDirTest(
-		 @Mocked FactoryUtil factoryUtil,
-		 @Mocked File mockOutputFile) throws IOException {
-
-		File parentDir = new File("target/test-output/generating-file-visitor/mydir");
-		new Expectations(mockOutputFile, parentDir) {{
-			FactoryUtil.createFile(anyString); result = mockOutputFile;
-			mockOutputFile.exists(); result = false;
-			mockOutputFile.getParentFile(); result = parentDir;
-			parentDir.isDirectory(); result = false;
-		}};
-
-		OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
-		builder.addPomLastModifiedTimestamp(0);
-		File file = new File(dataDir, "mydir/missing-var-test.txt.json");
-		builder.addGeneratorLocation(file.toPath());
-		File outputFile = new File(outputDir, "mydir/missing-var-test.txt");
-		builder.addOutputLocation(outputFile.toPath());
-		File templateFile = new File(templateDir, "test.ftl"); //this is missing a
-		builder.addTemplateLocation(templateFile.toPath());
-		builder.addDataModel(dataModel);
-		OutputGenerator generator = builder.create();
-		Assertions.assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
-			generator.generate(config);
-		}).withMessage("Could not create directory: " + parentDir.getAbsoluteFile().toString());
-	}
+    private File testDir = new File("src/test/data/generating-file-visitor");
+    private File dataDir = new File(testDir, "data");
+    private File templateDir = new File(testDir, "template");
+    private File outputDir = new File("target/test-output/generating-file-visitor");
+    private Configuration config;
+    private Map<String, Object> dataModel = new HashMap<String, Object>();
+
+    @BeforeMethod
+    public void setupDataModel() {
+        dataModel.clear();
+        dataModel.put("testVar", "test value");
+        dataModel.put("pomProperties", new HashMap<String, String>());
+        ((Map<String, String>) dataModel.get("pomProperties")).put("pomVar", "pom value");
+    }
+
+    @BeforeClass
+    public static void cleanFields() throws IOException {
+        // Clean output dir before each run.
+        File outputDir = new File("target/test-output/generating-file-visitor");
+        if (outputDir.exists()) {
+            // Recursively delete output from previous run.
+            Files.walk(outputDir.toPath())
+                    .sorted(Comparator.reverseOrder())
+                    .map(Path::toFile)
+                    .forEach(File::delete);
+        }
+    }
+
+    @BeforeMethod
+    public void before() throws IOException {
+        if (!testDir.isDirectory()) {
+            throw new RuntimeException("Can't find required test data directory. "
+                    + "If running test outside of maven, make sure working directory is the project directory. "
+                    + "Looking for: " + testDir);
+        }
+
+        config = new Configuration(Configuration.VERSION_2_3_23);
+        config.setDefaultEncoding("UTF-8");
+        config.setTemplateLoader(new FileTemplateLoader(templateDir));
+    }
+
+    @Test
+    public void createTest() {
+        OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            builder.create();
+        }).withMessage("Must set the pomModifiedTimestamp");
+
+        builder.addPomLastModifiedTimestamp(0);
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            builder.create();
+        }).withMessage("Must set a non-null generatorLocation");
+
+        File file = new File(dataDir, "mydir/success-test.txt.json");
+        builder.addGeneratorLocation(file.toPath());
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            builder.create();
+        }).withMessage("Must set a non-null templateLocation");
+
+        File templateFile = new File(templateDir, "test.ftl");
+        builder.addTemplateLocation(templateFile.toPath());
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            builder.create();
+        }).withMessage("Must set a non-null outputLocation");
+
+        File outputFile = new File(outputDir, "mydir/success-test.txt");
+        builder.addOutputLocation(outputFile.toPath());
+
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            builder.create();
+        }).withMessage("Must set a non-null dataModel");
+
+        builder.addDataModel(dataModel);
+        OutputGenerator generator = builder.create();
+
+        assertEquals(0, generator.pomModifiedTimestamp);
+        assertEquals(file.toPath(), generator.generatorLocation);
+        assertEquals(templateFile.toPath(), generator.templateLocation);
+        assertEquals(outputFile.toPath(), generator.outputLocation);
+        assertEquals(dataModel.size(), generator.dataModel.size());
+        assertArrayEquals(dataModel.entrySet().toArray(), generator.dataModel.entrySet().toArray());
+    }
+
+    @Test
+    public void addToDataModelTest() {
+        OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            builder.create();
+        }).withMessage("Must set the pomModifiedTimestamp");
+
+        builder.addPomLastModifiedTimestamp(0);
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            builder.create();
+        }).withMessage("Must set a non-null generatorLocation");
+
+        File file = new File(dataDir, "mydir/success-test.txt.json");
+        builder.addGeneratorLocation(file.toPath());
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            builder.create();
+        }).withMessage("Must set a non-null templateLocation");
+
+        File templateFile = new File(templateDir, "test.ftl");
+        builder.addTemplateLocation(templateFile.toPath());
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            builder.create();
+        }).withMessage("Must set a non-null outputLocation");
+
+        File outputFile = new File(outputDir, "mydir/success-test.txt");
+        builder.addOutputLocation(outputFile.toPath());
+
+        assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> {
+            builder.create();
+        }).withMessage("Must set a non-null dataModel");
+
+        builder.addToDataModel("testVar", "testVal");
+        OutputGenerator generator = builder.create();
+
+        assertEquals(1, generator.dataModel.size());
+        assertEquals("testVal", generator.dataModel.get("testVar"));
+
+        builder.addDataModel(dataModel);
+        builder.addToDataModel("testVar2", "testVal2");
+
+        generator = builder.create();
+
+        assertEquals(3, generator.dataModel.size());
+        assertEquals("test value", generator.dataModel.get("testVar"));
+        assertEquals("testVal2", generator.dataModel.get("testVar2"));
+    }
+
+    @Test
+    public void generate_SuccessTest()
+            throws IOException {
+        OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
+        builder.addPomLastModifiedTimestamp(0);
+        File file = new File(dataDir, "mydir/success-test.txt.json");
+        builder.addGeneratorLocation(file.toPath());
+        File outputFile = new File(outputDir, "mydir/success-test.txt");
+        builder.addOutputLocation(outputFile.toPath());
+        File templateFile = new File(templateDir, "test.ftl");
+        builder.addTemplateLocation(templateFile.toPath());
+        builder.addDataModel(dataModel);
+        OutputGenerator generator = builder.create();
+        generator.generate(config);
+
+        assertTrue(outputFile.isFile());
+        List<String> lines = Files.readAllLines(outputFile.toPath(), StandardCharsets.UTF_8);
+        assertEquals(1, lines.size());
+        assertEquals("This is a test freemarker template. Test json data: 'test value'. Test pom data: 'pom value'.", lines
+                .get(0));
+
+        // Process same file again, should not regenerate file.
+        long lastMod = outputFile.lastModified();
+        generator.generate(config);
+        assertEquals(lastMod, outputFile.lastModified());
+
+        // Set mod time to before json file.
+        lastMod = file.lastModified() - 1000; // File system may only keep 1 second precision.
+        outputFile.setLastModified(lastMod);
+        generator.generate(config);
+        assertTrue(lastMod < outputFile.lastModified());
+
+        // Set mod time to before template file.
+        lastMod = templateFile.lastModified() - 1000; // File system may only keep 1 second precision.
+        outputFile.setLastModified(lastMod);
+        generator.generate(config);
+        assertTrue(lastMod < outputFile.lastModified());
+    }
+
+    @Test
+    public void generate_badTemplateNameTest() {
+        OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
+        builder.addPomLastModifiedTimestamp(0);
+        File file = new File(dataDir, "mydir/bad-template-name.txt.json");
+        builder.addGeneratorLocation(file.toPath());
+        File outputFile = new File(outputDir, "mydir/bad-template-name.txt");
+        builder.addOutputLocation(outputFile.toPath());
+        File templateFile = new File(templateDir, "missing.ftl"); //this doesn't exist
+        builder.addTemplateLocation(templateFile.toPath());
+        builder.addDataModel(dataModel);
+        OutputGenerator generator = builder.create();
+        Assertions.assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
+            generator.generate(config);
+        }).withMessage("Could not read template: missing.ftl");
+    }
+
+    @Test
+    public void generate_missingVarTest() {
+        OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
+        builder.addPomLastModifiedTimestamp(0);
+        File file = new File(dataDir, "mydir/missing-var-test.txt.json");
+        builder.addGeneratorLocation(file.toPath());
+        File outputFile = new File(outputDir, "mydir/missing-var-test.txt");
+        builder.addOutputLocation(outputFile.toPath());
+        File templateFile = new File(templateDir, "test.ftl"); //this is missing a
+        builder.addTemplateLocation(templateFile.toPath());
+        dataModel.remove("testVar");
+        builder.addDataModel(dataModel);
+        OutputGenerator generator = builder.create();
+        Assertions.assertThatExceptionOfType(RuntimeException.class)
+                .isThrownBy(() -> {
+                    generator.generate(config);
+                })
+                .withMessage("Could not process template associated with data file: src/test/data/generating-file-visitor/data/mydir/missing-var-test.txt.json");
+    }
+
+    @Test
+    public void generate_badParentTest() throws IOException {
+        OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
+        builder.addPomLastModifiedTimestamp(0);
+        File file = new File(dataDir, "badParent/bad-parent-test.txt.json");
+        builder.addGeneratorLocation(file.toPath());
+        File outputFile = new File(outputDir, "badParent/bad-parent-test.txt");
+        builder.addOutputLocation(outputFile.toPath());
+        File templateFile = new File(templateDir, "test.ftl"); //this is missing a
+        builder.addTemplateLocation(templateFile.toPath());
+        builder.addDataModel(dataModel);
+        OutputGenerator generator = builder.create();
+        outputDir.mkdirs();
+        outputFile.getParentFile().createNewFile();
+
+        Assertions.assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
+            generator.generate(config);
+        }).withMessage("Parent directory of output file is a file: " + outputFile.getParentFile().getAbsolutePath());
+    }
+
+    @Test
+    public void generate_cantCreateOutputFileParentDirTest(
+            @Mocked FactoryUtil factoryUtil,
+            @Mocked File mockOutputFile) throws IOException {
+
+        File parentDir = new File("target/test-output/generating-file-visitor/mydir");
+        new Expectations(mockOutputFile, parentDir) {{
+            FactoryUtil.createFile(anyString);
+            result = mockOutputFile;
+            mockOutputFile.exists();
+            result = false;
+            mockOutputFile.getParentFile();
+            result = parentDir;
+            parentDir.isDirectory();
+            result = false;
+        }};
+
+        OutputGenerator.OutputGeneratorBuilder builder = OutputGenerator.builder();
+        builder.addPomLastModifiedTimestamp(0);
+        File file = new File(dataDir, "mydir/missing-var-test.txt.json");
+        builder.addGeneratorLocation(file.toPath());
+        File outputFile = new File(outputDir, "mydir/missing-var-test.txt");
+        builder.addOutputLocation(outputFile.toPath());
+        File templateFile = new File(templateDir, "test.ftl"); //this is missing a
+        builder.addTemplateLocation(templateFile.toPath());
+        builder.addDataModel(dataModel);
+        OutputGenerator generator = builder.create();
+        Assertions.assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
+            generator.generate(config);
+        }).withMessage("Could not create directory: " + parentDir.getAbsoluteFile().toString());
+    }
 }