Repository: vackosar/gitflow-incremental-builder
Pull request #242 (2020-08-30 17:58:28)

Central workaround for MNG-6979 & replace topLevelProject with currentProject
- moves workaround introduced via #239 to Configuration.currentProject and simplifies exec root check
- uses Configuration.currentProject consequently in "production code" (instead of MavenSession.getCurrentProject())
- drops usage of topLevelProject in favor of currentProject to allow for GIB config overrides or additions in submodules
- updates from 3.11.4-SNAPSHOT to 3.12.0-SNAPSHOT (change too big, BOM support is also planned)
- side quest: clean up GitProviderTest by using (and refactor) EmptyLocalRepoMock

/cc @mickroll @gastaldi 


Patch:
diff --git a/pom.xml b/pom.xml
index db12aec..f2cac80 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.vackosar.gitflowincrementalbuilder</groupId>
     <artifactId>gitflow-incremental-builder</artifactId>
-    <version>3.11.4-SNAPSHOT</version>
+    <version>3.12.0-SNAPSHOT</version>
     <name>${project.groupId}:${project.artifactId}</name>
     <description>A maven extension for incremental building of multi-module projects when using Git Flow.</description>
     <url>https://github.com/vackosar/gitflow-incremental-builder</url>
@@ -641,12 +641,12 @@
                                         <limit>
                                             <counter>INSTRUCTION</counter>
                                             <value>COVEREDRATIO</value>
-                                            <minimum>0.92</minimum>
+                                            <minimum>0.93</minimum>
                                         </limit>
                                         <limit>
                                             <counter>BRANCH</counter>
                                             <value>COVEREDRATIO</value>
-                                            <minimum>0.83</minimum>
+                                            <minimum>0.84</minimum>
                                         </limit>
                                         <limit>
                                             <counter>CLASS</counter>
diff --git a/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/Configuration.java b/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/Configuration.java
index 4665d88..da82914 100644
--- a/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/Configuration.java
+++ b/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/Configuration.java
@@ -36,6 +36,7 @@ public class Configuration {
     public static final String PLUGIN_KEY = "com.vackosar.gitflowincrementalbuilder:gitflow-incremental-builder";
 
     public final MavenSession mavenSession;
+    public final MavenProject currentProject;
 
     public final boolean help;
     public final boolean disable;
@@ -70,7 +71,9 @@ public class Configuration {
 
     public Configuration(MavenSession session) {
         this.mavenSession = session;
-        Properties[] properties = getProperties(session, logger);
+        this.currentProject = findCurrentProject(session);
+
+        Properties[] properties = getProperties(currentProject, logger);
         Properties projectProperties = properties[0];
         Properties pluginProperties = properties[1];
 
@@ -174,12 +177,25 @@ public class Configuration {
         return expectedMakeBehavior.equals(actualMakeBehavior) || MavenExecutionRequest.REACTOR_MAKE_BOTH.equals(actualMakeBehavior);
     }
 
-    private static Properties[] getProperties(MavenSession session, Logger logger) {
-        MavenProject mavenProject = Optional.ofNullable(session.getTopLevelProject()).orElseGet(session::getCurrentProject);
-        if (mavenProject != null) {
-            return new Properties[] { mavenProject.getProperties(), getPluginProperties(mavenProject) };
+    private static MavenProject findCurrentProject(MavenSession session) {
+        // MavenSession.getCurrentProject() does not return the correct value in some cases,
+        // see: https://issues.apache.org/jira/browse/MNG-6979
+        MavenProject currentProject = session.getCurrentProject();
+        if (currentProject == null || !currentProject.isExecutionRoot()) {
+            currentProject = session.getProjects().stream()
+                    .filter(MavenProject::isExecutionRoot)
+                    .findAny()
+                    .orElse(currentProject);
+        }
+        // design note: could theoretically call session.setCurrentProject(...) here, but this seems too risky
+        return currentProject;
+    }
+
+    private static Properties[] getProperties(MavenProject currentProject, Logger logger) {
+        if (currentProject != null) {
+            return new Properties[] { currentProject.getProperties(), getPluginProperties(currentProject) };
         } else {
-            logger.warn("gitflow-incremental-builder could not parse configuration due to missing 'topLevel' or 'current' project in the MavenSession.");
+            logger.warn("gitflow-incremental-builder could not parse configuration due to missing 'current' project in the MavenSession.");
             Properties fakeProjectProperties = new Properties();
             fakeProjectProperties.put(Property.disable.prefixedName(), Boolean.TRUE.toString());
             return new Properties[] { fakeProjectProperties, new Properties() };
diff --git a/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemover.java b/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemover.java
index c680b82..1a6b317 100644
--- a/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemover.java
+++ b/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemover.java
@@ -54,9 +54,9 @@ class UnchangedProjectsRemover {
         // - building non-recursively (-N)
         // - or only one "leaf" project/module is present (cases: mvn -f ... or cd ... or unusual case of non-multi-module project)
         // the assumption here (similar to the -pl approach above): the user has decided to build a single module, so don't mess with that
-        if (!config.mavenSession.getRequest().isRecursive() || onlySingleLeafModulePresent(config.mavenSession)) {
+        if (!config.mavenSession.getRequest().isRecursive() || onlySingleLeafModulePresent(config)) {
             printDelimiter();
-            logger.info("Building single project (without any adjustment): {}", config.mavenSession.getCurrentProject().getArtifactId());
+            logger.info("Building single project (without any adjustment): {}", config.currentProject.getArtifactId());
             return;
         }
 
@@ -100,9 +100,9 @@ class UnchangedProjectsRemover {
         return !selected.isEmpty() && mavenSession.getProjects().equals(new ArrayList<>(selected));
     }
 
-    private boolean onlySingleLeafModulePresent(MavenSession mavenSession) {
+    private boolean onlySingleLeafModulePresent(Configuration config) {
         // note: explicit check for modules to cover -N case
-        return mavenSession.getProjects().size() == 1 && mavenSession.getCurrentProject().getModel().getModules().isEmpty();
+        return config.mavenSession.getProjects().size() == 1 && config.currentProject.getModel().getModules().isEmpty();
     }
 
     private void handleNoChangesDetected(Set<MavenProject> selected, Configuration config) {
@@ -125,24 +125,12 @@ class UnchangedProjectsRemover {
             config.mavenSession.getProjects().stream().forEach(proj -> applyUpstreamModuleArgs(proj, config));
         } else {
             logger.info("No changed artifacts detected: Executing validate goal on current project only, skipping all submodules.");
-            config.mavenSession.setProjects(Collections.singletonList(getCurrentProject(config.mavenSession)));
+            config.mavenSession.setProjects(Collections.singletonList(config.currentProject));
             config.mavenSession.getGoals().clear();
             config.mavenSession.getGoals().add("validate");
         }
     }
 
-    private MavenProject getCurrentProject(MavenSession mavenSession) {
-        // MavenSession.getCurrentProject() does not return the correct value in some cases
-        String executionRootDirectory = mavenSession.getExecutionRootDirectory();
-        if (executionRootDirectory == null) {
-            return mavenSession.getCurrentProject();
-        }
-        return mavenSession.getProjects().stream()
-                .filter(p -> (p.getFile() != null && executionRootDirectory.equals(p.getFile().getParent())))
-                .findFirst()
-                .orElse(mavenSession.getCurrentProject());
-    }
-
     private Set<MavenProject> calculateImpactedProjects(Set<MavenProject> selected, Set<MavenProject> changed, Configuration config) {
         Stream<MavenProject> impacted = selected.isEmpty() ? changed.stream() : Stream.concat(selected.stream(), changed.stream()).distinct();
         // note: buildAll *always* needs impacted incl. downstream, otherwise applyNotImpactedModuleArgs() might disable tests etc. for downstream modules!
diff --git a/src/main/java/com/vackosar/gitflowincrementalbuild/control/jgit/GitProvider.java b/src/main/java/com/vackosar/gitflowincrementalbuild/control/jgit/GitProvider.java
index 4af3aa3..5ecb2db 100644
--- a/src/main/java/com/vackosar/gitflowincrementalbuild/control/jgit/GitProvider.java
+++ b/src/main/java/com/vackosar/gitflowincrementalbuild/control/jgit/GitProvider.java
@@ -54,7 +54,7 @@ public class GitProvider {
 
     private Git setupGit(Configuration config) throws IOException {
         final FileRepositoryBuilder builder = new FileRepositoryBuilder();
-        File pomDir = config.mavenSession.getCurrentProject().getBasedir().toPath().toFile();
+        File pomDir = config.currentProject.getBasedir();
         builder.findGitDir(pomDir);
         if (builder.getGitDir() == null) {
             String gitDirNotFoundMessage = "Git repository root directory not found ascending from current working directory:'"


Test patch:
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/BaseUnchangedProjectsRemoverTest.java b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/BaseUnchangedProjectsRemoverTest.java
index 75c3e3e..7be2347 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/BaseUnchangedProjectsRemoverTest.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/BaseUnchangedProjectsRemoverTest.java
@@ -88,7 +88,6 @@ public abstract class BaseUnchangedProjectsRemoverTest {
         moduleA = addModuleMock(AID_MODULE_A, false);
 
         when(mavenSessionMock.getCurrentProject()).thenReturn(moduleA);
-        when(mavenSessionMock.getTopLevelProject()).thenReturn(moduleA);
 
         when(mavenExecutionRequestMock.isRecursive()).thenReturn(true);
         when(mavenSessionMock.getRequest()).thenReturn(mavenExecutionRequestMock);
@@ -151,10 +150,9 @@ public abstract class BaseUnchangedProjectsRemoverTest {
         projects.clear();
         projects.addAll(Arrays.asList(moduleMocks));
 
-        // Maven shifts currentProject and topLevelProject to the first(!) project (as per Maven 3.6.3 with -pl and -f)
+        // Maven shifts currentProject to the first(!) project (as per Maven 3.6.3 with -pl and -f)
         MavenProject firstProject = moduleMocks[0];
         when(mavenSessionMock.getCurrentProject()).thenReturn(firstProject);
-        when(mavenSessionMock.getTopLevelProject()).thenReturn(firstProject);
     }
 
     protected void assertProjectPropertiesEqual(MavenProject project, String... expectedFlat) {
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/ConfigurationTest.java b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/ConfigurationTest.java
index 0aad6fa..512d417 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/ConfigurationTest.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/ConfigurationTest.java
@@ -1,5 +1,6 @@
 package com.vackosar.gitflowincrementalbuild.boundary;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -12,6 +13,8 @@ import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -27,6 +30,7 @@ import org.codehaus.plexus.util.xml.Xpp3Dom;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 
@@ -43,6 +47,9 @@ import com.vackosar.gitflowincrementalbuild.control.Property;
 @ExtendWith({SystemPropertiesResetExtension.class, MockitoExtension.class})
 public class ConfigurationTest {
 
+    @TempDir
+    Path tempDir;
+
     @Mock
     private MavenExecutionRequest mavenExecutionRequestMock;
 
@@ -50,7 +57,7 @@ public class ConfigurationTest {
     private MavenSession mavenSessionMock;
 
     @Mock(lenient = true)
-    private MavenProject mockTLProject;
+    private MavenProject currentProjectMock;
 
     private final Properties projectProperties = new Properties();
 
@@ -58,8 +65,8 @@ public class ConfigurationTest {
     void before() {
         when(mavenSessionMock.getRequest()).thenReturn(mavenExecutionRequestMock);
 
-        when(mockTLProject.getProperties()).thenReturn(projectProperties);
-        when(mavenSessionMock.getTopLevelProject()).thenReturn(mockTLProject);
+        when(currentProjectMock.getProperties()).thenReturn(projectProperties);
+        when(mavenSessionMock.getCurrentProject()).thenReturn(currentProjectMock);
     }
 
     @Test
@@ -72,6 +79,42 @@ public class ConfigurationTest {
                 .withMessageContaining(Property.disableBranchComparison.prefixedName());
     }
 
+    @Test
+    public void mavenSession() {
+        Configuration configuration = new Configuration(mavenSessionMock);
+
+        assertThat(configuration.mavenSession).isSameAs(mavenSessionMock);
+    }
+
+    @Test
+    public void currentProject_execRoot() {
+        MavenProject execRootProject = mock(MavenProject.class);
+        when(execRootProject.isExecutionRoot()).thenReturn(true);
+        when(execRootProject.getProperties()).thenReturn(new Properties());
+        when(mavenSessionMock.getProjects()).thenReturn(Arrays.asList(currentProjectMock, execRootProject));
+
+        Configuration configuration = new Configuration(mavenSessionMock);
+
+        assertThat(configuration.currentProject).isSameAs(execRootProject);
+    }
+
+    @Test
+    public void currentProject_execRootNoMatch() {
+        MavenProject execRootProject = mock(MavenProject.class);
+        when(mavenSessionMock.getProjects()).thenReturn(Arrays.asList(currentProjectMock, execRootProject));
+
+        Configuration configuration = new Configuration(mavenSessionMock);
+
+        assertThat(configuration.currentProject).isSameAs(currentProjectMock);
+    }
+
+    @Test
+    public void currentProject_noExecRoot() {
+        Configuration configuration = new Configuration(mavenSessionMock);
+
+        assertThat(configuration.currentProject).isSameAs(currentProjectMock);
+    }
+
     @Test
     public void disable() {
         System.setProperty(Property.disable.prefixedName(), "true");
@@ -416,24 +459,14 @@ public class ConfigurationTest {
     }
 
     @Test
-    public void noTopLevelProject_noCurrentProject() {
-        when(mavenSessionMock.getTopLevelProject()).thenReturn(null);
+    public void noCurrentProject() {
+        when(mavenSessionMock.getCurrentProject()).thenReturn(null);
 
         Configuration configuration = new Configuration(mavenSessionMock);
 
         assertTrue(configuration.disable);
     }
 
-    @Test
-    public void noTopLevelProject_fallbackToCurrentProject() {
-        when(mavenSessionMock.getTopLevelProject()).thenReturn(null);
-        when(mavenSessionMock.getCurrentProject()).thenReturn(mockTLProject);
-
-        Configuration configuration = new Configuration(mavenSessionMock);
-
-        assertFalse(configuration.disable);
-    }
-
     @Test
     public void enabled_systemProperty() {
         System.setProperty(Property.enabled.prefixedName(), "false");
@@ -464,6 +497,6 @@ public class ConfigurationTest {
     private void mockPlugin(Xpp3Dom config) {
         Plugin pluginMock = mock(Plugin.class);
         when(pluginMock.getConfiguration()).thenReturn(config);
-        when(mockTLProject.getPlugin(Configuration.PLUGIN_KEY)).thenReturn(pluginMock);
+        when(currentProjectMock.getPlugin(Configuration.PLUGIN_KEY)).thenReturn(pluginMock);
     }
 }
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/MavenLifecycleParticipantTest.java b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/MavenLifecycleParticipantTest.java
index e66be24..cc075f2 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/MavenLifecycleParticipantTest.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/MavenLifecycleParticipantTest.java
@@ -58,9 +58,9 @@ public class MavenLifecycleParticipantTest {
 
     @BeforeEach
     void before() {
-        MavenProject mockTLProject = mock(MavenProject.class);
-        when(mockTLProject.getProperties()).thenReturn(projectProperties);
-        when(mavenSessionMock.getTopLevelProject()).thenReturn(mockTLProject);
+        MavenProject currentProjectMock = mock(MavenProject.class);
+        when(currentProjectMock.getProperties()).thenReturn(projectProperties);
+        when(mavenSessionMock.getCurrentProject()).thenReturn(currentProjectMock);
 
         when(mavenSessionMock.getRequest()).thenReturn(mock(MavenExecutionRequest.class));
 
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/control/BaseDifferentFilesTest.java b/src/test/java/com/vackosar/gitflowincrementalbuild/control/BaseDifferentFilesTest.java
index 69fb3b8..ff56dce 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/control/BaseDifferentFilesTest.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/control/BaseDifferentFilesTest.java
@@ -73,7 +73,7 @@ public abstract class BaseDifferentFilesTest extends BaseRepoTest {
     }
 
     protected Set<Path> invokeUnderTest(final MavenSession mavenSessionMock) throws Exception {
-        mavenSessionMock.getTopLevelProject().getProperties().putAll(projectProperties);
+        mavenSessionMock.getCurrentProject().getProperties().putAll(projectProperties);
 
         DifferentFiles underTest = new DifferentFiles();
         GitProvider gitProvider = new GitProvider();
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/control/DifferentFilesTest.java b/src/test/java/com/vackosar/gitflowincrementalbuild/control/DifferentFilesTest.java
index f7e155b..837dd2d 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/control/DifferentFilesTest.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/control/DifferentFilesTest.java
@@ -9,13 +9,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.contains;
 import static org.mockito.Mockito.verify;
 
-import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
 import java.nio.file.StandardOpenOption;
 import java.util.Arrays;
 import java.util.Collections;
@@ -233,36 +230,32 @@ public class DifferentFilesTest extends BaseDifferentFilesTest {
 
     @Test
     public void emptyLocalRepo() throws Exception {
-        projectProperties.clear();  // special tests that does not follow the pattern of the test base classes
-        try (InputStream basicPomData = DifferentFilesTest.class.getResourceAsStream("/DifferentFilesTest/pom.xml");
-                EmptyLocalRepoMock emptyLocalRepoMock = new EmptyLocalRepoMock(getRepoBaseFolder())) {
-            File projectFolder = emptyLocalRepoMock.getBaseCanonicalBaseFolder();
-            Files.copy(basicPomData, new File(projectFolder, "pom.xml").toPath(), StandardCopyOption.REPLACE_EXISTING);
-            MavenSession mavenSessionMock = MavenSessionMock.get(projectFolder.toPath(), projectProperties);
+        projectProperties.clear();  // special test that does not follow the pattern of the test base classes
+
+        EmptyLocalRepoMock.withBasicPom(getRepoBaseFolder().toPath(), emptyLocalRepoMock -> {
+            MavenSession mavenSessionMock = MavenSessionMock.get(emptyLocalRepoMock.getRepoDir(), projectProperties);
 
             Throwable thrown = catchThrowable(() -> invokeUnderTest(mavenSessionMock));
 
             assertThat(thrown).isInstanceOf(SkipExecutionException.class);
             assertThat(thrown).hasMessageContaining("'HEAD'");
-        }
+        });
     }
 
     @Test
     public void localRepoButNoRemoteRepo() throws Exception {
-        projectProperties.clear();  // special tests that does not follow the pattern of the test base classes
-        try (InputStream basicPomData = DifferentFilesTest.class.getResourceAsStream("/DifferentFilesTest/pom.xml");
-                EmptyLocalRepoMock emptyLocalRepoMock = new EmptyLocalRepoMock(getRepoBaseFolder())) {
-            File projectFolder = emptyLocalRepoMock.getBaseCanonicalBaseFolder();
-            Files.copy(basicPomData, new File(projectFolder, "pom.xml").toPath(), StandardCopyOption.REPLACE_EXISTING);
+        projectProperties.clear();  // special test that does not follow the pattern of the test base classes
+
+        EmptyLocalRepoMock.withBasicPom(getRepoBaseFolder().toPath(), emptyLocalRepoMock -> {
             emptyLocalRepoMock.getGit().add().addFilepattern("pom.xml").call();
             emptyLocalRepoMock.getGit().commit().setMessage("initial commit with pom.xml").call();
-            MavenSession mavenSessionMock = MavenSessionMock.get(projectFolder.toPath(), projectProperties);
+            MavenSession mavenSessionMock = MavenSessionMock.get(emptyLocalRepoMock.getRepoDir(), projectProperties);
 
             Throwable thrown = catchThrowable(() -> invokeUnderTest(mavenSessionMock));
 
             assertThat(thrown).isInstanceOf(SkipExecutionException.class);
             assertThat(thrown).hasMessageContaining(Property.referenceBranch.getDefaultValue());
-        }
+        });
     }
 
     private Path modifyTrackedFile(Path repoPath) throws IOException {
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/jgit/GitProviderTest.java b/src/test/java/com/vackosar/gitflowincrementalbuild/jgit/GitProviderTest.java
index 130c72a..d1b07be 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/jgit/GitProviderTest.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/jgit/GitProviderTest.java
@@ -4,8 +4,11 @@ import com.vackosar.gitflowincrementalbuild.boundary.Configuration;
 import com.vackosar.gitflowincrementalbuild.control.Property;
 import com.vackosar.gitflowincrementalbuild.control.jgit.GitProvider;
 import com.vackosar.gitflowincrementalbuild.entity.SkipExecutionException;
+import com.vackosar.gitflowincrementalbuild.mocks.EmptyLocalRepoMock;
+
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.project.MavenProject;
+import org.eclipse.jgit.api.errors.GitAPIException;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -14,16 +17,13 @@ import org.junit.jupiter.api.io.TempDir;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 
-import java.io.File;
 import java.io.IOException;
+import java.net.URISyntaxException;
 import java.util.Properties;
 import java.nio.file.Path;
 
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
@@ -35,47 +35,36 @@ public class GitProviderTest {
     @Mock
     private MavenSession mavenSessionMock;
 
-    private GitProvider underTest = new GitProvider();
+    @Mock
+    private MavenProject currentProjectMock;
+
+    private final GitProvider underTest = new GitProvider();
 
     @BeforeEach
-    public void setup() {
-        MavenProject projectMock = mock(MavenProject.class);
-        when(projectMock.getProperties()).thenReturn(new Properties());
-        projectMock.getProperties().put(Property.disable.prefixedName(), "true"); // otherwise unrelated stuff in MavenSession would need mocking
-        when(mavenSessionMock.getTopLevelProject()).thenReturn(projectMock);
+    void setup() {
+        when(currentProjectMock.getProperties()).thenReturn(new Properties());
+        currentProjectMock.getProperties().put(Property.disable.prefixedName(), "true"); // otherwise unrelated stuff in MavenSession would need mocking
+        when(mavenSessionMock.getCurrentProject()).thenReturn(currentProjectMock);
     }
 
     @AfterEach
-    public void tearDown() {
+    void tearDown() {
         underTest.close();
     }
 
     @Test
-    public void test_simple() throws IOException {
-        initSimple();
-        assertNotNull(underTest.get(new Configuration(mavenSessionMock)));
-
-        verify(mavenSessionMock).getCurrentProject();
-    }
+    public void get() throws IOException, URISyntaxException, GitAPIException {
+        EmptyLocalRepoMock.withBasicPom(tempDir, emptyLocalRepoMock -> {
+            when(currentProjectMock.getBasedir()).thenReturn(emptyLocalRepoMock.getRepoDir().toFile());
 
-    private void initSimple() throws IOException {
-        MavenProject mavenProject = new MavenProject();
-        File pomXmlInCwd = new File("pom.xml").getCanonicalFile();
-        File pomXmlInParent = new File("..", "pom.xml").getCanonicalFile();
-        mavenProject.setFile(pomXmlInParent);
-        if (pomXmlInCwd.exists()) {
-            mavenProject.setFile(pomXmlInCwd);
-        }
-        doReturn(mavenProject).when(mavenSessionMock).getCurrentProject();
+            assertNotNull(underTest.get(new Configuration(mavenSessionMock)));
+        });
     }
 
     @Test
-    public void test_no_git_dir() {
+    public void get_noGitDir() {
 
-        MavenProject mavenProject = new MavenProject();
-        File pom = new File(tempDir.toFile(), "pom.xml");
-        mavenProject.setFile(pom);
-        doReturn(mavenProject).when(mavenSessionMock).getCurrentProject();
+        when(currentProjectMock.getBasedir()).thenReturn(tempDir.toFile());
 
         assertThrows(SkipExecutionException.class, () -> underTest.get(new Configuration(mavenSessionMock)));
     }
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/mocks/EmptyLocalRepoMock.java b/src/test/java/com/vackosar/gitflowincrementalbuild/mocks/EmptyLocalRepoMock.java
index 611cf95..30cbd8c 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/mocks/EmptyLocalRepoMock.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/mocks/EmptyLocalRepoMock.java
@@ -1,26 +1,30 @@
 package com.vackosar.gitflowincrementalbuild.mocks;
 
-import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URISyntaxException;
-
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.errors.GitAPIException;
 
+import com.vackosar.gitflowincrementalbuild.control.DifferentFilesTest;
+
 public class EmptyLocalRepoMock implements AutoCloseable {
 
     static {
         JGitIsolation.ensureIsolatedFromSystemAndUserConfig();
     }
 
-    private final File baseFolder;
+    private final Path repoDir;
     private final Git git;
 
-    public EmptyLocalRepoMock(File allReposBaseFolder) throws IOException, URISyntaxException, GitAPIException {
-        this.baseFolder = new File(allReposBaseFolder.getAbsolutePath(), "tmp/emptyrepo/");
-        this.baseFolder.mkdirs();
-        
-        git = Git.init().setDirectory(baseFolder).call();
+    public EmptyLocalRepoMock(Path allReposBaseDir) throws IOException, URISyntaxException, GitAPIException {
+        this.repoDir = allReposBaseDir.toAbsolutePath().resolve("tmp/emptyrepo/");
+        Files.createDirectories(repoDir);
+
+        git = Git.init().setDirectory(repoDir.toFile()).call();
     }
 
     public Git getGit() {
@@ -35,7 +39,20 @@ public class EmptyLocalRepoMock implements AutoCloseable {
         }
     }
 
-    public File getBaseCanonicalBaseFolder() throws IOException {
-        return baseFolder.getCanonicalFile();
+    public Path getRepoDir() throws IOException {
+        return repoDir;
+    }
+
+    public static void withBasicPom(Path allReposBaseDir, Callback callback) throws IOException, URISyntaxException, GitAPIException {
+        try (InputStream basicPomData = DifferentFilesTest.class.getResourceAsStream("/pom-basic.xml");
+                EmptyLocalRepoMock emptyLocalRepoMock = new EmptyLocalRepoMock(allReposBaseDir)) {
+            Files.copy(basicPomData, emptyLocalRepoMock.repoDir.resolve("pom.xml"), StandardCopyOption.REPLACE_EXISTING);
+
+            callback.invoke(emptyLocalRepoMock);
+        }
+    }
+
+    public static interface Callback {
+        void invoke(EmptyLocalRepoMock emptyLocalRepoMock) throws GitAPIException, IOException;
     }
 }
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/mocks/MavenSessionMock.java b/src/test/java/com/vackosar/gitflowincrementalbuild/mocks/MavenSessionMock.java
index c8376fc..87433a8 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/mocks/MavenSessionMock.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/mocks/MavenSessionMock.java
@@ -27,7 +27,7 @@ public class MavenSessionMock {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(MavenSessionMock.class);
 
-    public static MavenSession get(Path workDir, Properties topLevelProjectProperties) throws Exception {
+    public static MavenSession get(Path workDir, Properties topLevelProjectProperties) throws IOException {
         PomFinder finder = new PomFinder();
         Files.walkFileTree(workDir, finder);
         List<MavenProject> projects = finder.projects.stream()
@@ -35,15 +35,14 @@ public class MavenSessionMock {
                 .map(MavenSessionMock::createProject)
                 .collect(Collectors.toList());
 
-        MavenProject topLevelProject = projects.get(0);
-        topLevelProject.getModel().setProperties(topLevelProjectProperties);
+        MavenProject currentProject = projects.get(0);
+        currentProject.getModel().setProperties(topLevelProjectProperties);
         MavenSession mavenSession = mock(MavenSession.class, withSettings().lenient());
-        when(mavenSession.getCurrentProject()).thenReturn(topLevelProject);
+        when(mavenSession.getCurrentProject()).thenReturn(currentProject);
         MavenExecutionRequest request = mock(MavenExecutionRequest.class);
         when(mavenSession.getRequest()).thenReturn(request);
         when(mavenSession.getAllProjects()).thenReturn(projects);
         when(mavenSession.getProjects()).thenReturn(projects);
-        when(mavenSession.getTopLevelProject()).thenReturn(topLevelProject);
         ProjectDependencyGraph dependencyGraphMock = mock(ProjectDependencyGraph.class);
         when(mavenSession.getProjectDependencyGraph()).thenReturn(dependencyGraphMock);
         return mavenSession;