diff --git a/.github/workflows/maven-verify.yml b/.github/workflows/maven-verify.yml
index 932827c..0df1d93 100644
--- a/.github/workflows/maven-verify.yml
+++ b/.github/workflows/maven-verify.yml
@@ -25,3 +25,6 @@ jobs:
   build:
     name: Verify
     uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v4
+    with:
+      ff-maven: "4.0.0-alpha-4"                     # Maven version for fail-fast-build
+      maven-matrix: '[ "4.0.0-alpha-4" ]'
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index c5a01aa..c2848ca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,11 +23,12 @@ under the License.
   <parent>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-plugins</artifactId>
-    <version>41</version>
+    <version>42</version>
+    <relativePath />
   </parent>
 
   <artifactId>maven-resources-plugin</artifactId>
-  <version>3.3.2-SNAPSHOT</version>
+  <version>4.0.0-SNAPSHOT</version>
   <packaging>maven-plugin</packaging>
 
   <name>Apache Maven Resources Plugin</name>
@@ -71,62 +72,56 @@ under the License.
   </distributionManagement>
 
   <properties>
-    <mavenFilteringVersion>3.3.2</mavenFilteringVersion>
-    <mavenVersion>3.2.5</mavenVersion>
-    <javaVersion>8</javaVersion>
+    <mavenFilteringVersion>4.0.0-SNAPSHOT</mavenFilteringVersion>
+    <mavenVersion>4.0.0-beta-3</mavenVersion>
+    <mavenPluginPluginVersion>4.0.0-SNAPSHOT</mavenPluginPluginVersion>
+    <javaVersion>17</javaVersion>
     <project.build.outputTimestamp>2023-03-21T12:01:37Z</project.build.outputTimestamp>
   </properties>
 
   <dependencies>
     <dependency>
       <groupId>org.apache.maven</groupId>
-      <artifactId>maven-plugin-api</artifactId>
+      <artifactId>maven-api-core</artifactId>
       <version>${mavenVersion}</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
-      <artifactId>maven-core</artifactId>
-      <version>${mavenVersion}</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-model</artifactId>
-      <version>${mavenVersion}</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-settings</artifactId>
+      <artifactId>maven-api-model</artifactId>
       <version>${mavenVersion}</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.maven.plugin-tools</groupId>
-      <artifactId>maven-plugin-annotations</artifactId>
-      <scope>provided</scope>
+      <groupId>jakarta.inject</groupId>
+      <artifactId>jakarta.inject-api</artifactId>
+      <version>2.0.1</version>
     </dependency>
+
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-interpolation</artifactId>
-      <version>1.27</version>
+      <version>1.26</version>
       <scope>runtime</scope>
     </dependency>
+    <!--
     <dependency>
       <groupId>org.eclipse.sisu</groupId>
       <artifactId>org.eclipse.sisu.plexus</artifactId>
-      <version>0.3.5</version>
+      <version>0.9.0.M2</version>
       <scope>provided</scope>
     </dependency>
+    -->
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
+      <version>4.0.0</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-xml</artifactId>
+      <version>4.0.2</version>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -134,47 +129,35 @@ under the License.
       <artifactId>maven-filtering</artifactId>
       <version>${mavenFilteringVersion}</version>
     </dependency>
+
     <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-      <version>2.16.0</version>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <version>5.10.1</version>
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-lang3</artifactId>
-      <version>3.14.0</version>
-      <scope>compile</scope>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-core</artifactId>
+      <version>${mavenVersion}</version>
+      <scope>test</scope>
     </dependency>
-
     <dependency>
       <groupId>org.apache.maven</groupId>
-      <artifactId>maven-compat</artifactId>
+      <artifactId>maven-xml-impl</artifactId>
       <version>${mavenVersion}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.plugin-testing</groupId>
       <artifactId>maven-plugin-testing-harness</artifactId>
-      <version>3.3.0</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.13.2</version>
+      <version>4.0.0-alpha-3-SNAPSHOT</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.resolver</groupId>
       <artifactId>maven-resolver-api</artifactId>
-      <version>1.6.3</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-simple</artifactId>
-      <version>1.7.36</version>
+      <version>1.8.2</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
@@ -191,6 +174,16 @@ under the License.
           </excludes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-plugin-plugin</artifactId>
+        <version>${mavenPluginPluginVersion}</version>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>3.2.1</version>
+      </plugin>
     </plugins>
   </build>
 
@@ -203,6 +196,7 @@ under the License.
             <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-invoker-plugin</artifactId>
+              <version>3.6.0</version>
               <configuration>
                 <debug>true</debug>
                 <postBuildHookScript>verify</postBuildHookScript>
@@ -221,26 +215,6 @@ under the License.
             </plugin>
           </plugins>
         </pluginManagement>
-        <plugins>
-          <plugin>
-            <groupId>org.eclipse.sisu</groupId>
-            <artifactId>sisu-maven-plugin</artifactId>
-          </plugin>
-          <!--
-           ! The following is used within the src/it/user-filters test.
-          -->
-          <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-jar-plugin</artifactId>
-            <executions>
-              <execution>
-                <goals>
-                  <goal>test-jar</goal>
-                </goals>
-              </execution>
-            </executions>
-          </plugin>
-        </plugins>
       </build>
     </profile>
   </profiles>
diff --git a/src/it/MRESOURCES-18/pom.xml b/src/it/MRESOURCES-18/pom.xml
index dca439a..153ac06 100644
--- a/src/it/MRESOURCES-18/pom.xml
+++ b/src/it/MRESOURCES-18/pom.xml
@@ -57,7 +57,7 @@ under the License.
       </plugin>
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
-        <version>2.4.3</version>
+        <version>3.2.1</version>
         <configuration>
           <systemProperties>
             <!-- pass this system property through to the tests -->
diff --git a/src/it/settings.xml b/src/it/settings.xml
index 61bdd13..2b9ce5b 100644
--- a/src/it/settings.xml
+++ b/src/it/settings.xml
@@ -32,9 +32,11 @@ under the License.
           <url>@localRepositoryUrl@</url>
           <releases>
             <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
           </releases>
           <snapshots>
             <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
           </snapshots>
         </repository>
         <repository>
@@ -42,9 +44,11 @@ under the License.
           <url>https://repository.apache.org/content/repositories/snapshots</url>
           <releases>
             <enabled>false</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
           </releases>
           <snapshots>
             <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
           </snapshots>
         </repository>
       </repositories>
@@ -54,9 +58,11 @@ under the License.
           <url>@localRepositoryUrl@</url>
           <releases>
             <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
           </releases>
           <snapshots>
             <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
           </snapshots>
         </pluginRepository>
       </pluginRepositories>
diff --git a/src/it/user-filters/filter/pom.xml b/src/it/user-filters/filter/pom.xml
new file mode 100644
index 0000000..a8ea5e4
--- /dev/null
+++ b/src/it/user-filters/filter/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.plugins.resources.its</groupId>
+  <artifactId>user-filters-filter</artifactId>
+  <version>1.0.16-SNAPSHOT</version>
+  <packaging>jar</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.shared</groupId>
+      <artifactId>maven-filtering</artifactId>
+      <version>@mavenFilteringVersion@</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/src/test/java/org/apache/maven/plugins/resources/filters/ItFilter.java b/src/it/user-filters/filter/src/main/java/org/apache/maven/plugins/resources/filters/ItFilter.java
similarity index 86%
rename from src/test/java/org/apache/maven/plugins/resources/filters/ItFilter.java
rename to src/it/user-filters/filter/src/main/java/org/apache/maven/plugins/resources/filters/ItFilter.java
index c0ebd2d..6d46ca1 100644
--- a/src/test/java/org/apache/maven/plugins/resources/filters/ItFilter.java
+++ b/src/it/user-filters/filter/src/main/java/org/apache/maven/plugins/resources/filters/ItFilter.java
@@ -18,16 +18,15 @@
  */
 package org.apache.maven.plugins.resources.filters;
 
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import java.io.File;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import org.apache.commons.io.FileUtils;
+import org.apache.maven.api.di.Named;
+import org.apache.maven.api.di.Singleton;
 import org.apache.maven.shared.filtering.MavenFilteringException;
 import org.apache.maven.shared.filtering.MavenResourcesExecution;
 import org.apache.maven.shared.filtering.MavenResourcesFiltering;
@@ -62,7 +61,7 @@ public boolean filteredFileExtension(String fileName, List<String> userNonFilter
     public void filterResources(MavenResourcesExecution mavenResourcesExecution) throws MavenFilteringException {
         System.out.println("ItFilter filterResources");
         try {
-            File f = new File(mavenResourcesExecution.getOutputDirectory(), "foo.txt");
+            Path f = mavenResourcesExecution.getOutputDirectory().resolve("foo.txt");
             List<String> lines = new ArrayList<>();
 
             lines.add("foo");
@@ -70,9 +69,10 @@ public void filterResources(MavenResourcesExecution mavenResourcesExecution) thr
             lines.add("toto="
                     + mavenResourcesExecution
                             .getMavenSession()
-                            .getSystemProperties()
-                            .getProperty("toto"));
-            FileUtils.writeLines(f, lines);
+                            .getUserProperties()
+                            .get("toto"));
+            Files.createDirectories(f.getParent());
+            Files.write(f, lines);
         } catch (IOException e) {
             throw new MavenFilteringException(e.getMessage(), e);
         }
diff --git a/src/it/user-filters/filter/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject b/src/it/user-filters/filter/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject
new file mode 100644
index 0000000..e86a5d2
--- /dev/null
+++ b/src/it/user-filters/filter/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.maven.plugins.resources.filters.ItFilter
diff --git a/src/it/user-filters/module/pom.xml b/src/it/user-filters/module/pom.xml
new file mode 100644
index 0000000..d0718e7
--- /dev/null
+++ b/src/it/user-filters/module/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.plugins.resources.its</groupId>
+  <artifactId>user-filters-module</artifactId>
+  <name>User Filter Resources Test</name>
+  <version>1.0.16-SNAPSHOT</version>
+  <build>
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+      <resource>
+        <filtering>true</filtering>
+        <directory>src/main/filtered</directory>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <version>@project.version@</version>
+        <configuration>
+          <encoding>UTF-8</encoding>
+          <mavenFilteringHints>
+            <mavenFilteringHint>itFilter</mavenFilteringHint>
+          </mavenFilteringHints>
+        </configuration>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.plugins.resources.its</groupId>
+            <artifactId>user-filters-filter</artifactId>
+            <version>1.0.16-SNAPSHOT</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+    </plugins>
+  </build>
+  <properties>
+    <escaped>this is escaped</escaped>
+    <escaped.at>this is escaped.at</escaped.at>
+    <foo>this is foo</foo>
+    <bar>this is bar</bar>
+  </properties>
+</project>
diff --git a/src/it/user-filters/src/main/filtered/filtered.properties b/src/it/user-filters/module/src/main/filtered/filtered.properties
similarity index 100%
rename from src/it/user-filters/src/main/filtered/filtered.properties
rename to src/it/user-filters/module/src/main/filtered/filtered.properties
diff --git a/src/it/user-filters/src/main/resources/unfiltered.properties b/src/it/user-filters/module/src/main/resources/unfiltered.properties
similarity index 100%
rename from src/it/user-filters/src/main/resources/unfiltered.properties
rename to src/it/user-filters/module/src/main/resources/unfiltered.properties
diff --git a/src/it/user-filters/pom.xml b/src/it/user-filters/pom.xml
index 7b8f887..ce5a980 100644
--- a/src/it/user-filters/pom.xml
+++ b/src/it/user-filters/pom.xml
@@ -21,45 +21,12 @@
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.apache.plugins.resources.its</groupId>
-  <artifactId>user-filters</artifactId>
-  <name>User Filter Resources Test</name>
+  <artifactId>user-filters-parent</artifactId>
   <version>1.0.16-SNAPSHOT</version>
-  <build>
-    <resources>
-      <resource>
-        <directory>src/main/resources</directory>
-      </resource>
-      <resource>
-        <filtering>true</filtering>
-        <directory>src/main/filtered</directory>
-      </resource>
-    </resources>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-resources-plugin</artifactId>
-        <version>@project.version@</version>
-        <configuration>
-          <encoding>UTF-8</encoding>
-          <mavenFilteringHints>
-            <mavenFilteringHint>itFilter</mavenFilteringHint>
-          </mavenFilteringHints>
-        </configuration>
-        <dependencies>
-          <dependency>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-resources-plugin</artifactId>
-            <version>@project.version@</version>
-            <classifier>tests</classifier>
-          </dependency>
-        </dependencies>
-      </plugin>
-    </plugins>
-  </build>
-  <properties>
-    <escaped>this is escaped</escaped>
-    <escaped.at>this is escaped.at</escaped.at>
-    <foo>this is foo</foo>
-    <bar>this is bar</bar>
-  </properties>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>filter</module>
+    <module>module</module>
+  </modules>
 </project>
diff --git a/src/it/user-filters/verify.groovy b/src/it/user-filters/verify.groovy
index 3749dc5..c4e343d 100644
--- a/src/it/user-filters/verify.groovy
+++ b/src/it/user-filters/verify.groovy
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-assert new File(basedir, 'target/classes/foo.txt').exists();
+assert new File(basedir, 'module/target/classes/foo.txt').exists();
 
-content = new File(basedir, 'target/classes/foo.txt').text;
+content = new File(basedir, 'module/target/classes/foo.txt').text;
 assert content.contains( 'foo');
 assert content.contains( 'version=1.0.16-SNAPSHOT');
 assert content.contains( 'toto=titi');
diff --git a/src/main/java/org/apache/maven/plugins/resources/CopyResourcesMojo.java b/src/main/java/org/apache/maven/plugins/resources/CopyResourcesMojo.java
index 1e62e0b..8bb5c1c 100644
--- a/src/main/java/org/apache/maven/plugins/resources/CopyResourcesMojo.java
+++ b/src/main/java/org/apache/maven/plugins/resources/CopyResourcesMojo.java
@@ -18,12 +18,12 @@
  */
 package org.apache.maven.plugins.resources;
 
-import java.io.File;
+import java.nio.file.Path;
 import java.util.List;
 
-import org.apache.maven.model.Resource;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.api.plugin.annotations.Mojo;
+import org.apache.maven.api.plugin.annotations.Parameter;
+import org.apache.maven.shared.filtering.Resource;
 
 /**
  * Copy resources of the configured plugin attribute resources
@@ -31,14 +31,14 @@
  * @author Olivier Lamy
  * @since 2.3
  */
-@Mojo(name = "copy-resources", threadSafe = true)
+@Mojo(name = "copy-resources")
 public class CopyResourcesMojo extends ResourcesMojo {
 
     /**
      * The output directory into which to copy the resources.
      */
     @Parameter(required = true)
-    private File outputDirectory;
+    private Path outputDirectory;
 
     /**
      * The list of resources we want to transfer. See the Maven Model for a
@@ -48,12 +48,12 @@ public class CopyResourcesMojo extends ResourcesMojo {
     private List<Resource> resources;
 
     /** {@inheritDoc} */
-    public File getOutputDirectory() {
+    public Path getOutputDirectory() {
         return outputDirectory;
     }
 
     /** {@inheritDoc} */
-    public void setOutputDirectory(File outputDirectory) {
+    public void setOutputDirectory(Path outputDirectory) {
         this.outputDirectory = outputDirectory;
     }
 
diff --git a/src/main/java/org/apache/maven/plugins/resources/MavenBuildTimestamp.java b/src/main/java/org/apache/maven/plugins/resources/MavenBuildTimestamp.java
index fb2f8f7..57a58e9 100644
--- a/src/main/java/org/apache/maven/plugins/resources/MavenBuildTimestamp.java
+++ b/src/main/java/org/apache/maven/plugins/resources/MavenBuildTimestamp.java
@@ -19,80 +19,61 @@
 package org.apache.maven.plugins.resources;
 
 import java.text.SimpleDateFormat;
+import java.time.Instant;
 import java.util.Date;
 import java.util.GregorianCalendar;
+import java.util.Map;
 import java.util.Properties;
 import java.util.TimeZone;
 
 /**
- * This class is duplicated from maven-model-builder from maven core. (See MRESOURCES-99).
+ * This class is duplicated from maven-api-impl from maven core. (See MRESOURCES-99).
  */
 public class MavenBuildTimestamp {
-    /**
-     * ISO 8601-compliant timestamp for machine readability
-     */
+    // ISO 8601-compliant timestamp for machine readability
     public static final String DEFAULT_BUILD_TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
 
-    /**
-     * The property name.
-     */
     public static final String BUILD_TIMESTAMP_FORMAT_PROPERTY = "maven.build.timestamp.format";
 
-    /**
-     * The default time zone {@code Etc/UTC}.
-     */
     public static final TimeZone DEFAULT_BUILD_TIME_ZONE = TimeZone.getTimeZone("Etc/UTC");
 
     private String formattedTimestamp;
 
-    /**
-     * Create an instance.
-     */
     public MavenBuildTimestamp() {
-        this(new Date());
+        this(Instant.now());
     }
 
-    /**
-     * @param time The time to use.
-     */
-    public MavenBuildTimestamp(Date time) {
+    public MavenBuildTimestamp(Instant time) {
         this(time, DEFAULT_BUILD_TIMESTAMP_FORMAT);
     }
 
-    /**
-     * @param time The time to use.
-     * @param properties the properties which can be define. can be {@code null}
-     */
-    public MavenBuildTimestamp(Date time, Properties properties) {
-        this(time, properties != null ? properties.getProperty(BUILD_TIMESTAMP_FORMAT_PROPERTY) : null);
+    public MavenBuildTimestamp(Instant time, Map<String, String> properties) {
+        this(time, properties != null ? properties.get(BUILD_TIMESTAMP_FORMAT_PROPERTY) : null);
     }
 
     /**
-     * @param time The time to use.
-     * @param timestampFormat The format for {@link SimpleDateFormat}.
+     *
+     * @deprecated Use {@link #MavenBuildTimestamp(Instant, Map)} or extract the format and pass it
+     *             to {@link #MavenBuildTimestamp(Instant, String)} instead.
      */
-    public MavenBuildTimestamp(Date time, String timestampFormat) {
-        SimpleDateFormat dateFormat;
+    @Deprecated
+    public MavenBuildTimestamp(Instant time, Properties properties) {
+        this(time, properties != null ? properties.getProperty(BUILD_TIMESTAMP_FORMAT_PROPERTY) : null);
+    }
 
+    public MavenBuildTimestamp(Instant time, String timestampFormat) {
         if (timestampFormat == null) {
-            dateFormat = new SimpleDateFormat(DEFAULT_BUILD_TIMESTAMP_FORMAT);
-        } else {
-            dateFormat = new SimpleDateFormat(timestampFormat);
+            timestampFormat = DEFAULT_BUILD_TIMESTAMP_FORMAT;
         }
-
-        dateFormat.setCalendar(new GregorianCalendar());
-        dateFormat.setTimeZone(DEFAULT_BUILD_TIME_ZONE);
-
         if (time == null) {
-            formattedTimestamp = dateFormat.format(new Date());
-        } else {
-            formattedTimestamp = dateFormat.format(time);
+            time = Instant.now();
         }
+        SimpleDateFormat dateFormat = new SimpleDateFormat(timestampFormat);
+        dateFormat.setCalendar(new GregorianCalendar());
+        dateFormat.setTimeZone(DEFAULT_BUILD_TIME_ZONE);
+        formattedTimestamp = dateFormat.format(new Date(time.toEpochMilli()));
     }
 
-    /**
-     * @return The formatted time stamp.
-     */
     public String formattedTimestamp() {
         return formattedTimestamp;
     }
diff --git a/src/main/java/org/apache/maven/plugins/resources/Resource.java b/src/main/java/org/apache/maven/plugins/resources/Providers.java
similarity index 72%
rename from src/main/java/org/apache/maven/plugins/resources/Resource.java
rename to src/main/java/org/apache/maven/plugins/resources/Providers.java
index 9f9c219..a9fe718 100644
--- a/src/main/java/org/apache/maven/plugins/resources/Resource.java
+++ b/src/main/java/org/apache/maven/plugins/resources/Providers.java
@@ -18,12 +18,16 @@
  */
 package org.apache.maven.plugins.resources;
 
-/**
- * @author Olivier Lamy
- * @since 2.3
- *
- */
-public class Resource extends org.apache.maven.model.Resource {
-    // nothing to do here just a class prevent users adding an implementation attribute
-    // in the mojo configuration
+import org.apache.maven.api.di.Named;
+import org.apache.maven.api.di.Provides;
+import org.sonatype.plexus.build.incremental.BuildContext;
+import org.sonatype.plexus.build.incremental.ThreadBuildContext;
+
+@Named
+class Providers {
+
+    @Provides
+    static BuildContext buildContext() {
+        return new ThreadBuildContext();
+    }
 }
diff --git a/src/main/java/org/apache/maven/plugins/resources/ResourceUtils.java b/src/main/java/org/apache/maven/plugins/resources/ResourceUtils.java
new file mode 100644
index 0000000..b6677f0
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/resources/ResourceUtils.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.plugins.resources;
+
+import org.apache.maven.shared.filtering.Resource;
+
+class ResourceUtils {
+
+    static Resource newResource(org.apache.maven.api.model.Resource res) {
+        Resource resource = new Resource();
+        resource.setDirectory(res.getDirectory());
+        resource.setFiltering(res.isFiltering());
+        resource.setExcludes(res.getExcludes());
+        resource.setIncludes(res.getIncludes());
+        resource.setMergeId(res.getMergeId());
+        resource.setTargetPath(res.getTargetPath());
+        return resource;
+    }
+}
diff --git a/src/main/java/org/apache/maven/plugins/resources/ResourcesMojo.java b/src/main/java/org/apache/maven/plugins/resources/ResourcesMojo.java
index a622653..6f699a6 100644
--- a/src/main/java/org/apache/maven/plugins/resources/ResourcesMojo.java
+++ b/src/main/java/org/apache/maven/plugins/resources/ResourcesMojo.java
@@ -18,7 +18,7 @@
  */
 package org.apache.maven.plugins.resources;
 
-import java.io.File;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -26,20 +26,21 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.model.Resource;
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugins.annotations.Component;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.project.MavenProject;
+import java.util.stream.Collectors;
+
+import org.apache.maven.api.Project;
+import org.apache.maven.api.ProjectScope;
+import org.apache.maven.api.Session;
+import org.apache.maven.api.di.Inject;
+import org.apache.maven.api.plugin.Log;
+import org.apache.maven.api.plugin.MojoException;
+import org.apache.maven.api.plugin.annotations.Mojo;
+import org.apache.maven.api.plugin.annotations.Parameter;
+import org.apache.maven.api.services.ProjectManager;
 import org.apache.maven.shared.filtering.MavenFilteringException;
 import org.apache.maven.shared.filtering.MavenResourcesExecution;
 import org.apache.maven.shared.filtering.MavenResourcesFiltering;
+import org.apache.maven.shared.filtering.Resource;
 
 /**
  * Copy resources for the main source code to the main output directory. Always uses the project.build.resources element
@@ -50,8 +51,8 @@
  * @author Andreas Hoheneder
  * @author William Ferguson
  */
-@Mojo(name = "resources", defaultPhase = LifecyclePhase.PROCESS_RESOURCES, requiresProject = true, threadSafe = true)
-public class ResourcesMojo extends AbstractMojo {
+@Mojo(name = "resources", defaultPhase = "process-resources", projectRequired = true)
+public class ResourcesMojo implements org.apache.maven.api.plugin.Mojo {
 
     /**
      * The character encoding to use when reading and writing filtered resources.
@@ -72,19 +73,19 @@ public class ResourcesMojo extends AbstractMojo {
      * The output directory into which to copy the resources.
      */
     @Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
-    private File outputDirectory;
+    protected Path outputDirectory;
 
     /**
      * The list of resources we want to transfer.
      */
-    @Parameter(defaultValue = "${project.resources}", required = true, readonly = true)
+    @Parameter
     private List<Resource> resources;
 
     /**
      *
      */
-    @Parameter(defaultValue = "${project}", readonly = true, required = true)
-    protected MavenProject project;
+    @Inject
+    protected Project project;
 
     /**
      * The list of additional filter properties files to be used along with System and project properties, which would
@@ -125,20 +126,20 @@ public class ResourcesMojo extends AbstractMojo {
     /**
      *
      */
-    @Component(role = MavenResourcesFiltering.class, hint = "default")
+    @Inject
     protected MavenResourcesFiltering mavenResourcesFiltering;
 
     /**
      *
      */
-    @Component(role = MavenResourcesFiltering.class)
+    @Inject
     protected Map<String, MavenResourcesFiltering> mavenResourcesFilteringMap;
 
     /**
      *
      */
-    @Parameter(defaultValue = "${session}", readonly = true, required = true)
-    protected MavenSession session;
+    @Inject
+    protected Session session;
 
     /**
      * Expressions preceded with this string won't be interpolated. Anything else preceded with this string will be
@@ -286,16 +287,27 @@ public class ResourcesMojo extends AbstractMojo {
     @Parameter(property = "maven.resources.skip", defaultValue = "false")
     private boolean skip;
 
-    /**
-     * {@inheritDoc}
-     */
-    public void execute() throws MojoExecutionException {
+    @Inject
+    private Log logger;
+
+    /** {@inheritDoc} */
+    public void execute() throws MojoException {
         if (isSkip()) {
             getLog().info("Skipping the execution.");
             return;
         }
 
-        if (StringUtils.isBlank(encoding) && isFilteringEnabled(getResources())) {
+        if (resources == null) {
+            resources = session.getService(ProjectManager.class).getResources(project, ProjectScope.MAIN).stream()
+                    .map(ResourceUtils::newResource)
+                    .collect(Collectors.toList());
+        }
+
+        doExecute();
+    }
+
+    protected void doExecute() throws MojoException {
+        if ((encoding == null || encoding.isEmpty()) && isFilteringEnabled(getResources())) {
             getLog().warn("File encoding has not been set, using platform encoding "
                     + System.getProperty("file.encoding")
                     + ". Build is platform dependent!");
@@ -344,7 +356,7 @@ public void execute() throws MojoExecutionException {
 
             executeUserFilterComponents(mavenResourcesExecution);
         } catch (MavenFilteringException e) {
-            throw new MojoExecutionException(e.getMessage(), e);
+            throw new MojoException(e.getMessage(), e);
         }
     }
 
@@ -366,23 +378,20 @@ private Properties addSeveralSpecialProperties() {
         String timeStamp = new MavenBuildTimestamp().formattedTimestamp();
         Properties additionalProperties = new Properties();
         additionalProperties.put("maven.build.timestamp", timeStamp);
-        if (project.getBasedir() != null) {
-            additionalProperties.put(
-                    "project.baseUri",
-                    project.getBasedir().getAbsoluteFile().toURI().toString());
-        }
-
+        additionalProperties.put(
+                "project.baseUri",
+                project.getBasedir().toAbsolutePath().toFile().toURI().toString());
         return additionalProperties;
     }
 
     /**
      * @param mavenResourcesExecution {@link MavenResourcesExecution}
-     * @throws MojoExecutionException  in case of wrong lookup.
+     * @throws MojoException  in case of wrong lookup.
      * @throws MavenFilteringException in case of failure.
      * @since 2.5
      */
     protected void executeUserFilterComponents(MavenResourcesExecution mavenResourcesExecution)
-            throws MojoExecutionException, MavenFilteringException {
+            throws MojoException, MavenFilteringException {
 
         if (mavenFilteringHints != null) {
             for (String hint : mavenFilteringHints) {
@@ -391,7 +400,7 @@ protected void executeUserFilterComponents(MavenResourcesExecution mavenResource
                     getLog().debug("added user filter component with hint: " + hint);
                     mavenFilteringComponents.add(userFilterComponent);
                 } else {
-                    throw new MojoExecutionException(
+                    throw new MojoException(
                             "User filter with hint `" + hint + "` requested, but not present. Discovered filters are: "
                                     + mavenResourcesFilteringMap.keySet());
                 }
@@ -461,14 +470,14 @@ public void setResources(List<Resource> resources) {
     /**
      * @return {@link #outputDirectory}
      */
-    public File getOutputDirectory() {
+    public Path getOutputDirectory() {
         return outputDirectory;
     }
 
     /**
      * @param outputDirectory the output folder.
      */
-    public void setOutputDirectory(File outputDirectory) {
+    public void setOutputDirectory(Path outputDirectory) {
         this.outputDirectory = outputDirectory;
     }
 
@@ -548,4 +557,8 @@ public void setUseDefaultDelimiters(boolean useDefaultDelimiters) {
     public boolean isSkip() {
         return skip;
     }
+
+    protected Log getLog() {
+        return logger;
+    }
 }
diff --git a/src/main/java/org/apache/maven/plugins/resources/TestResourcesMojo.java b/src/main/java/org/apache/maven/plugins/resources/TestResourcesMojo.java
index f7a1ada..ac90676 100644
--- a/src/main/java/org/apache/maven/plugins/resources/TestResourcesMojo.java
+++ b/src/main/java/org/apache/maven/plugins/resources/TestResourcesMojo.java
@@ -18,14 +18,16 @@
  */
 package org.apache.maven.plugins.resources;
 
-import java.io.File;
+import java.nio.file.Path;
 import java.util.List;
+import java.util.stream.Collectors;
 
-import org.apache.maven.model.Resource;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.api.ProjectScope;
+import org.apache.maven.api.plugin.MojoException;
+import org.apache.maven.api.plugin.annotations.Mojo;
+import org.apache.maven.api.plugin.annotations.Parameter;
+import org.apache.maven.api.services.ProjectManager;
+import org.apache.maven.shared.filtering.Resource;
 
 /**
  * Copy resources for the test source code to the test output directory.
@@ -34,22 +36,18 @@
  * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
  * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
  */
-@Mojo(
-        name = "testResources",
-        defaultPhase = LifecyclePhase.PROCESS_TEST_RESOURCES,
-        requiresProject = true,
-        threadSafe = true)
+@Mojo(name = "testResources", defaultPhase = "process-test-resources", projectRequired = true)
 public class TestResourcesMojo extends ResourcesMojo {
     /**
      * The output directory into which to copy the resources.
      */
     @Parameter(defaultValue = "${project.build.testOutputDirectory}", required = true)
-    private File outputDirectory;
+    private Path outputDirectory;
 
     /**
      * The list of resources we want to transfer.
      */
-    @Parameter(defaultValue = "${project.testResources}", required = true)
+    @Parameter
     private List<Resource> resources;
 
     /**
@@ -63,21 +61,28 @@ public class TestResourcesMojo extends ResourcesMojo {
     /**
      * {@inheritDoc}
      */
-    public void execute() throws MojoExecutionException {
+    public void execute() throws MojoException {
         if (skip) {
             getLog().info("Not copying test resources");
-        } else {
-            super.execute();
+            return;
         }
+
+        if (resources == null) {
+            resources = session.getService(ProjectManager.class).getResources(project, ProjectScope.TEST).stream()
+                    .map(ResourceUtils::newResource)
+                    .collect(Collectors.toList());
+        }
+
+        super.doExecute();
     }
 
     /** {@inheritDoc} */
-    public File getOutputDirectory() {
+    public Path getOutputDirectory() {
         return outputDirectory;
     }
 
     /** {@inheritDoc} */
-    public void setOutputDirectory(File outputDirectory) {
+    public void setOutputDirectory(Path outputDirectory) {
         this.outputDirectory = outputDirectory;
     }
 
diff --git a/src/test/java/org/apache/maven/plugins/resources/AbstractPropertyUtilsTest.java b/src/test/java/org/apache/maven/plugins/resources/AbstractPropertyUtilsTest.java
index 2f7579b..f186998 100644
--- a/src/test/java/org/apache/maven/plugins/resources/AbstractPropertyUtilsTest.java
+++ b/src/test/java/org/apache/maven/plugins/resources/AbstractPropertyUtilsTest.java
@@ -18,33 +18,33 @@
  */
 package org.apache.maven.plugins.resources;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Enumeration;
 import java.util.Properties;
 
-import org.apache.maven.plugin.testing.AbstractMojoTestCase;
-import org.codehaus.plexus.util.IOUtil;
+import org.junit.jupiter.api.BeforeEach;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 /**
  * Base class for propertyutils test case
  */
-public abstract class AbstractPropertyUtilsTest extends AbstractMojoTestCase {
-    protected File propertyFile;
+public abstract class AbstractPropertyUtilsTest {
+    protected Path propertyFile;
 
-    protected File validationFile;
+    protected Path validationFile;
 
     protected Properties validationProp;
 
-    protected abstract File getPropertyFile();
+    protected abstract Path getPropertyFile();
 
-    protected abstract File getValidationFile();
+    protected abstract Path getValidationFile();
 
+    @BeforeEach
     protected void setUp() throws Exception {
-        super.setUp();
-
         // load data
         propertyFile = getPropertyFile();
         assertNotNull(propertyFile);
@@ -78,19 +78,12 @@ protected boolean validateProperties(Properties prop) {
      *
      * @param validationPropFile
      */
-    private void loadValidationProperties(File validationPropFile) {
+    private void loadValidationProperties(Path validationPropFile) {
         validationProp = new Properties();
-        InputStream in = null;
-
-        try {
-            in = Files.newInputStream(validationPropFile.toPath());
+        try (InputStream in = Files.newInputStream(validationPropFile)) {
             validationProp.load(in);
-            in.close();
-            in = null;
         } catch (IOException ex) {
             // TODO: do error handling
-        } finally {
-            IOUtil.close(in);
         }
     }
 }
diff --git a/src/test/java/org/apache/maven/plugins/resources/BasicPropertyUtilsTest.java b/src/test/java/org/apache/maven/plugins/resources/BasicPropertyUtilsTest.java
index 9d31283..e7ceb0c 100644
--- a/src/test/java/org/apache/maven/plugins/resources/BasicPropertyUtilsTest.java
+++ b/src/test/java/org/apache/maven/plugins/resources/BasicPropertyUtilsTest.java
@@ -18,31 +18,41 @@
  */
 package org.apache.maven.plugins.resources;
 
-import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Properties;
 
+import org.apache.maven.api.plugin.testing.MojoTest;
 import org.apache.maven.shared.filtering.PropertyUtils;
+import org.junit.jupiter.api.Test;
 
+import static org.apache.maven.api.plugin.testing.MojoExtension.getBasedir;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@MojoTest
 public class BasicPropertyUtilsTest extends AbstractPropertyUtilsTest {
     protected static final String validationFileName =
-            "/target/test-classes/unit/propertiesutils-test/basic_validation.properties";
+            "target/test-classes/unit/propertiesutils-test/basic_validation.properties";
 
-    protected static final String propFileName = "/target/test-classes/unit/propertiesutils-test/basic.properties";
+    protected static final String propFileName = "target/test-classes/unit/propertiesutils-test/basic.properties";
 
-    protected File getPropertyFile() {
-        File propFile = new File(getBasedir(), propFileName);
+    protected Path getPropertyFile() {
+        Path propFile = Paths.get(getBasedir(), propFileName);
 
-        if (!propFile.exists()) {
+        if (!Files.exists(propFile)) {
             propFile = null;
         }
 
         return propFile;
     }
 
-    protected File getValidationFile() {
-        File validationFile = new File(getBasedir(), validationFileName);
+    protected Path getValidationFile() {
+        Path validationFile = Paths.get(getBasedir(), validationFileName);
 
-        if (!validationFile.exists()) {
+        if (!Files.exists(validationFile)) {
             validationFile = null;
         }
 
@@ -54,6 +64,7 @@ protected File getValidationFile() {
      *
      * @throws Exception
      */
+    @Test
     public void testBasicLoadProperty_FF() throws Exception {
         Properties prop = PropertyUtils.loadPropertyFile(propertyFile, false, false);
 
@@ -66,6 +77,7 @@ public void testBasicLoadProperty_FF() throws Exception {
      *
      * @throws Exception
      */
+    @Test
     public void testBasicLoadProperty_TF() throws Exception {
         Properties prop = PropertyUtils.loadPropertyFile(propertyFile, true, false);
 
@@ -78,6 +90,7 @@ public void testBasicLoadProperty_TF() throws Exception {
      *
      * @throws Exception
      */
+    @Test
     public void testBasicLoadProperty_TT() throws Exception {
         Properties prop = PropertyUtils.loadPropertyFile(propertyFile, true, true);
 
@@ -91,6 +104,7 @@ public void testBasicLoadProperty_TT() throws Exception {
      *
      * @throws Exception
      */
+    @Test
     public void testNonExistentProperty() throws Exception {
         Properties prop = PropertyUtils.loadPropertyFile(propertyFile, true, true);
 
diff --git a/src/test/java/org/apache/maven/plugins/resources/CopyResourcesMojoTest.java b/src/test/java/org/apache/maven/plugins/resources/CopyResourcesMojoTest.java
index e951fc1..6c928d1 100644
--- a/src/test/java/org/apache/maven/plugins/resources/CopyResourcesMojoTest.java
+++ b/src/test/java/org/apache/maven/plugins/resources/CopyResourcesMojoTest.java
@@ -18,51 +18,61 @@
  */
 package org.apache.maven.plugins.resources;
 
-import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Collections;
 
-import org.apache.maven.model.Resource;
-import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import org.apache.maven.api.Project;
+import org.apache.maven.api.di.Provides;
+import org.apache.maven.api.di.Singleton;
+import org.apache.maven.api.plugin.testing.Basedir;
+import org.apache.maven.api.plugin.testing.InjectMojo;
+import org.apache.maven.api.plugin.testing.MojoTest;
+import org.apache.maven.api.plugin.testing.stubs.SessionMock;
+import org.apache.maven.internal.impl.InternalSession;
 import org.apache.maven.plugins.resources.stub.MavenProjectResourcesStub;
-import org.codehaus.plexus.util.FileUtils;
+import org.apache.maven.shared.filtering.Resource;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+import static org.apache.maven.api.plugin.testing.MojoExtension.*;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
  * @author Olivier Lamy
  * @version $Id$
  */
-public class CopyResourcesMojoTest extends AbstractMojoTestCase {
-
-    protected static final String defaultPomFilePath = "/target/test-classes/unit/resources-test/plugin-config.xml";
-
-    File outputDirectory = new File(getBasedir(), "/target/copyResourcesTests");
-
-    protected void setUp() throws Exception {
-        super.setUp();
-        if (!outputDirectory.exists()) {
-            outputDirectory.mkdirs();
-        } else {
-            FileUtils.cleanDirectory(outputDirectory);
-        }
-    }
-
-    public void testCopyWithoutFiltering() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-
-        mojo.setOutputDirectory(outputDirectory);
+@MojoTest
+public class CopyResourcesMojoTest {
 
+    @Test
+    @InjectMojo(goal = "resources", pom = "classpath:/unit/resources-test/plugin-config.xml")
+    @Basedir
+    public void testCopyWithoutFiltering(ResourcesMojo mojo) throws Exception {
         Resource resource = new Resource();
-        resource.setDirectory(getBasedir() + "/src/test/unit-files/copy-resources-test/no-filter");
+        resource.setDirectory(getPluginBasedir() + "/src/test/unit-files/copy-resources-test/no-filter");
         resource.setFiltering(false);
-
         mojo.setResources(Collections.singletonList(resource));
 
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("CopyResourcesMojoTest");
-        File targetFile = new File(getBasedir(), "/target/copyResourcesTests");
-        project.setBaseDir(targetFile);
-        setVariableValueToObject(mojo, "project", project);
         mojo.execute();
 
-        assertTrue(new File(targetFile, "config.properties").exists());
+        Path result = mojo.outputDirectory.resolve("config.properties");
+        assertTrue(Files.exists(result), result + " does not exist");
+    }
+
+    private static final String LOCAL_REPO = "/target/local-repo";
+
+    @Provides
+    @Singleton
+    @SuppressWarnings("unused")
+    private static InternalSession getMockSession() {
+        return SessionMock.getMockSession(getBasedir() + LOCAL_REPO);
+    }
+
+    @Provides
+    @Singleton
+    @SuppressWarnings("unused")
+    private static Project createProject(ExtensionContext context) throws Exception {
+        return new MavenProjectResourcesStub();
     }
 }
diff --git a/src/test/java/org/apache/maven/plugins/resources/PropertyUtilsExceptionTest.java b/src/test/java/org/apache/maven/plugins/resources/PropertyUtilsExceptionTest.java
index 18f5aa1..915e084 100644
--- a/src/test/java/org/apache/maven/plugins/resources/PropertyUtilsExceptionTest.java
+++ b/src/test/java/org/apache/maven/plugins/resources/PropertyUtilsExceptionTest.java
@@ -18,21 +18,23 @@
  */
 package org.apache.maven.plugins.resources;
 
-import java.io.File;
 import java.io.FileNotFoundException;
+import java.nio.file.Paths;
 
 import org.apache.maven.shared.filtering.PropertyUtils;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 public class PropertyUtilsExceptionTest {
 
     /**
      * load property test case can be adjusted by modifying the basic.properties and basic_validation properties
-     *
-     * @throws Exception
      */
-    @Test(expected = FileNotFoundException.class)
-    public void loadPropertyFileShouldFailWithFileNotFoundException() throws Exception {
-        PropertyUtils.loadPropertyFile(new File("NON_EXISTENT_FILE"), true, true);
+    @Test
+    public void loadPropertyFileShouldFailWithFileNotFoundException() {
+        assertThrows(
+                FileNotFoundException.class,
+                () -> PropertyUtils.loadPropertyFile(Paths.get("NON_EXISTENT_FILE"), true, true));
     }
 }
diff --git a/src/test/java/org/apache/maven/plugins/resources/ResourcesMojoTest.java b/src/test/java/org/apache/maven/plugins/resources/ResourcesMojoTest.java
index cfac851..a79d68a 100644
--- a/src/test/java/org/apache/maven/plugins/resources/ResourcesMojoTest.java
+++ b/src/test/java/org/apache/maven/plugins/resources/ResourcesMojoTest.java
@@ -19,49 +19,61 @@
 package org.apache.maven.plugins.resources;
 
 import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileReader;
 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.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Properties;
-
-import org.apache.maven.execution.DefaultMavenExecutionRequest;
-import org.apache.maven.execution.MavenExecutionRequest;
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.model.Resource;
-import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import java.util.stream.Collectors;
+
+import org.apache.maven.api.Project;
+import org.apache.maven.api.di.Provides;
+import org.apache.maven.api.di.Singleton;
+import org.apache.maven.api.plugin.testing.Basedir;
+import org.apache.maven.api.plugin.testing.InjectMojo;
+import org.apache.maven.api.plugin.testing.MojoTest;
+import org.apache.maven.api.plugin.testing.stubs.SessionMock;
+import org.apache.maven.internal.impl.InternalSession;
 import org.apache.maven.plugins.resources.stub.MavenProjectResourcesStub;
-import org.codehaus.plexus.util.FileUtils;
+import org.apache.maven.shared.filtering.Resource;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.maven.api.plugin.testing.MojoExtension.getBasedir;
+import static org.apache.maven.api.plugin.testing.MojoExtension.setVariableValueToObject;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-public class ResourcesMojoTest extends AbstractMojoTestCase {
-    protected static final String defaultPomFilePath = "/target/test-classes/unit/resources-test/plugin-config.xml";
+@MojoTest
+public class ResourcesMojoTest {
+
+    private static final String CONFIG_XML = "classpath:/unit/resources-test/plugin-config.xml";
 
     /**
      * test mojo lookup, test harness should be working fine
-     *
-     * @throws Exception
      */
-    public void testHarnessEnvironment() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testHarnessEnvironment(ResourcesMojo mojo) {
         assertNotNull(mojo);
     }
 
     /**
-     * @throws Exception
      */
-    public void testResourceDirectoryStructure() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("resourceDirectoryStructure");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testResourceDirectoryStructure(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
         project.addFile("file4.txt");
         project.addFile("package/file3.nottest");
         project.addFile("notpackage/file1.include");
@@ -70,33 +82,31 @@ public void testResourceDirectoryStructure() throws Exception {
         project.setupBuildEnvironment();
 
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
 
         String resourcesDir = project.getOutputDirectory();
 
-        assertTrue(FileUtils.fileExists(resourcesDir + "/file4.txt"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/package/file3.nottest"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/notpackage/file1.include"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/package/test"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/notpackage/test"));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/file4.txt")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/package/file3.nottest")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/notpackage/file1.include")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/package/test")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/notpackage/test")));
     }
 
     /**
-     * @throws Exception
      */
-    public void testResourceDirectoryStructure_RelativePath() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("resourceDirectoryStructure_RelativePath");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testResourceDirectoryStructure_RelativePath(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
         project.setOutputDirectory("../relative_dir");
         project.addFile("file4.txt");
         project.addFile("package/file3.nottest");
@@ -105,63 +115,59 @@ public void testResourceDirectoryStructure_RelativePath() throws Exception {
         project.addFile("notpackage/test/file2.txt");
         project.setupBuildEnvironment();
 
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
+        setVariableValueToObject(mojo, "resources", getResources(project));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
 
         String resourcesDir = project.getOutputDirectory();
 
-        assertTrue(FileUtils.fileExists(resourcesDir + "/file4.txt"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/package/file3.nottest"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/notpackage/file1.include"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/package/test"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/notpackage/test"));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/file4.txt")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/package/file3.nottest")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/notpackage/file1.include")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/package/test")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/notpackage/test")));
     }
 
     /**
-     * @throws Exception
      */
-    public void testResourceEncoding() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("encoding");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testResourceEncoding(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
         project.addFile("file4.txt");
-        project.setResourceFiltering(0, true);
+        project.setResourceFiltering(true);
         project.setupBuildEnvironment();
 
         setVariableValueToObject(mojo, "encoding", "UTF-8");
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
 
         String resourcesDir = project.getOutputDirectory();
 
-        assertTrue(FileUtils.fileExists(resourcesDir + "/file4.txt"));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/file4.txt")));
     }
 
     /**
-     * @throws Exception
      */
-    public void testResourceInclude() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("resourceInclude");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testResourceInclude(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
         project.addFile("file1.include");
         project.addFile("file2.exclude");
         project.addFile("file3.nottest");
@@ -185,34 +191,32 @@ public void testResourceInclude() throws Exception {
         project.addInclude("**/test/file*");
         project.addInclude("**/package/*.include");
 
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
+        setVariableValueToObject(mojo, "resources", getResources(project));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
 
         String resourcesDir = project.getOutputDirectory();
 
-        assertTrue(FileUtils.fileExists(resourcesDir + "/package/test"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/file1.include"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/package/file1.include"));
-        assertFalse(FileUtils.fileExists(resourcesDir + "/notpackage/file1.include"));
-        assertFalse(FileUtils.fileExists(resourcesDir + "/notpackage/nottest/file.txt"));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/package/test")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/file1.include")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/package/file1.include")));
+        assertFalse(Files.exists(Paths.get(resourcesDir + "/notpackage/file1.include")));
+        assertFalse(Files.exists(Paths.get(resourcesDir + "/notpackage/nottest/file.txt")));
     }
 
     /**
-     * @throws Exception
      */
-    public void testResourceExclude() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("resourceExclude");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testResourceExclude(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
         project.addFile("file1.include");
         project.addFile("file2.exclude");
         project.addFile("file3.nottest");
@@ -237,34 +241,32 @@ public void testResourceExclude() throws Exception {
         project.addExclude("**/notpackage*");
         project.addExclude("**/notpackage*/**");
 
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
+        setVariableValueToObject(mojo, "resources", getResources(project));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
 
         String resourcesDir = project.getOutputDirectory();
 
-        assertTrue(FileUtils.fileExists(resourcesDir + "/package/test"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/file1.include"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/package/file1.include"));
-        assertFalse(FileUtils.fileExists(resourcesDir + "/notpackage/file1.include"));
-        assertFalse(FileUtils.fileExists(resourcesDir + "/notpackage/nottest/file.txt"));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/package/test")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/file1.include")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/package/file1.include")));
+        assertFalse(Files.exists(Paths.get(resourcesDir + "/notpackage/file1.include")));
+        assertFalse(Files.exists(Paths.get(resourcesDir + "/notpackage/nottest/file.txt")));
     }
 
     /**
-     * @throws Exception
      */
-    public void testResourceTargetPath() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("resourceTargetPath");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testResourceTargetPath(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
         project.setTargetPath("org/apache/maven/plugin/test");
 
         project.addFile("file4.txt");
@@ -274,90 +276,82 @@ public void testResourceTargetPath() throws Exception {
         project.addFile("notpackage/test/file2.txt");
         project.setupBuildEnvironment();
 
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
+        setVariableValueToObject(mojo, "resources", getResources(project));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
 
         String resourcesDir = project.getOutputDirectory();
 
-        assertTrue(FileUtils.fileExists(resourcesDir + "/org/apache/maven/plugin/test/file4.txt"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/org/apache/maven/plugin/test/package/file3.nottest"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/org/apache/maven/plugin/test/notpackage/file1.include"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/org/apache/maven/plugin/test/package/test"));
-        assertTrue(FileUtils.fileExists(resourcesDir + "/org/apache/maven/plugin/test/notpackage/test"));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/org/apache/maven/plugin/test/file4.txt")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/org/apache/maven/plugin/test/package/file3.nottest")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/org/apache/maven/plugin/test/notpackage/file1.include")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/org/apache/maven/plugin/test/package/test")));
+        assertTrue(Files.exists(Paths.get(resourcesDir + "/org/apache/maven/plugin/test/notpackage/test")));
     }
 
     /**
-     * @throws Exception
      */
-    public void testResourceSystemProperties_Filtering() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("resourceSystemProperties_Filtering");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testResourceSystemProperties_Filtering(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
         project.addFile("file4.txt", "current-working-directory = ${user.dir}");
-        project.setResourceFiltering(0, true);
+        project.setResourceFiltering(true);
         project.setupBuildEnvironment();
 
         // setVariableValueToObject(mojo,"encoding","UTF-8");
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         setVariableValueToObject(mojo, "escapeWindowsPaths", Boolean.TRUE);
 
-        MavenExecutionRequest request = new DefaultMavenExecutionRequest();
-        request.setSystemProperties(System.getProperties());
+        mojo.session.getSystemProperties().put("user.dir", System.getProperty("user.dir"));
 
-        MavenSession mavenSession = new MavenSession(null, null, request, null);
-        setVariableValueToObject(mojo, "session", mavenSession);
         mojo.execute();
 
         String resourcesDir = project.getOutputDirectory();
 
-        File userDir = new File(System.getProperty("user.dir"));
-        assertTrue(userDir.exists());
+        Path userDir = Paths.get(System.getProperty("user.dir"));
+        assertTrue(Files.exists(userDir));
 
         Properties props = new Properties();
-        try (FileInputStream inStream = new FileInputStream(new File(resourcesDir, "file4.txt"))) {
+        try (InputStream inStream = Files.newInputStream(Paths.get(resourcesDir, "file4.txt"))) {
             props.load(inStream);
         }
-        File fileFromFiltering = new File(props.getProperty("current-working-directory"));
+        Path fileFromFiltering = Paths.get(props.getProperty("current-working-directory"));
 
-        assertTrue(fileFromFiltering.getAbsolutePath() + " does not exist.", fileFromFiltering.exists());
-        assertEquals(userDir.getAbsolutePath(), fileFromFiltering.getAbsolutePath());
+        assertTrue(Files.exists(fileFromFiltering), fileFromFiltering.toAbsolutePath() + " does not exist.");
+        assertEquals(userDir.toAbsolutePath(), fileFromFiltering.toAbsolutePath());
     }
 
     /**
-     * @throws Exception
      */
-    public void testResourceProjectProperties_Filtering() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("resourceProjectProperties_Filtering");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testResourceProjectProperties_Filtering(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
         project.addFile("file4.txt", "current working directory = ${user.dir}");
-        project.setResourceFiltering(0, true);
+        project.setResourceFiltering(true);
         project.addProperty("user.dir", "FPJ kami!!!");
         project.setupBuildEnvironment();
 
         // setVariableValueToObject(mojo,"encoding","UTF-8");
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
@@ -369,19 +363,17 @@ public void testResourceProjectProperties_Filtering() throws Exception {
     }
 
     /**
-     * @throws Exception
      */
-    public void testProjectProperty_Filtering_PropertyDestination() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project =
-                new MavenProjectResourcesStub("resourcePojectProperty_Filtering_PropertyDestination");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testProjectProperty_Filtering_PropertyDestination(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
         project.addFile("file4.properties", "current working directory=${description}");
-        project.setResourceFiltering(0, true);
+        project.setResourceFiltering(true);
         project.setupBuildEnvironment();
 
         // setup dummy property
@@ -389,9 +381,8 @@ public void testProjectProperty_Filtering_PropertyDestination() throws Exception
 
         // setVariableValueToObject(mojo,"encoding","UTF-8");
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         setVariableValueToObject(mojo, "escapeWindowsPaths", Boolean.TRUE);
@@ -404,28 +395,27 @@ public void testProjectProperty_Filtering_PropertyDestination() throws Exception
     }
 
     /**
-     * @throws Exception
      */
-    public void testPropertyFiles_Filtering() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("resourcePropertyFiles_Filtering");
-        List<Resource> resources = project.getBuild().getResources();
-        LinkedList<String> filterList = new LinkedList<>();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testPropertyFiles_Filtering(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
+        LinkedList<String> filterList = new LinkedList<>();
+
         project.addFile("file4.properties", "current working directory=${dir}");
         project.addFile("filter.properties", "dir:testdir");
-        project.setResourceFiltering(0, true);
+        project.setResourceFiltering(true);
         project.setupBuildEnvironment();
         filterList.add(project.getResourcesDirectory() + "filter.properties");
 
         // setVariableValueToObject(mojo,"encoding","UTF-8");
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", filterList);
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
@@ -437,28 +427,27 @@ public void testPropertyFiles_Filtering() throws Exception {
     }
 
     /**
-     * @throws Exception
      */
-    public void testPropertyFiles_Extra() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("resourcePropertyFiles_Extra");
-        List<Resource> resources = project.getBuild().getResources();
-        LinkedList<String> filterList = new LinkedList<>();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testPropertyFiles_Extra(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
+        LinkedList<String> filterList = new LinkedList<>();
+
         project.addFile("extra.properties", "current working directory=${dir}");
         project.addFile("filter.properties", "dir:testdir");
-        project.setResourceFiltering(0, true);
+        project.setResourceFiltering(true);
         project.setupBuildEnvironment();
         filterList.add(project.getResourcesDirectory() + "filter.properties");
 
         // setVariableValueToObject(mojo,"encoding","UTF-8");
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "filters", filterList);
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
@@ -470,22 +459,22 @@ public void testPropertyFiles_Extra() throws Exception {
     }
 
     /**
-     * @throws Exception
      */
-    public void testPropertyFiles_MainAndExtra() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("resourcePropertyFiles_MainAndExtra");
-        List<Resource> resources = project.getBuild().getResources();
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testPropertyFiles_MainAndExtra(ResourcesMojo mojo) throws Exception {
+        assertNotNull(mojo);
+
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
         LinkedList<String> filterList = new LinkedList<>();
         LinkedList<String> extraFilterList = new LinkedList<>();
 
-        assertNotNull(mojo);
-
         project.addFile("main-extra.properties", "current working directory=${dir}; old working directory=${dir2}");
         project.addFile("filter.properties", "dir:testdir");
         project.addFile("extra-filter.properties", "dir2:testdir2");
-        project.setResourceFiltering(0, true);
+        project.setResourceFiltering(true);
 
         project.cleanBuildEnvironment();
         project.setupBuildEnvironment();
@@ -495,9 +484,8 @@ public void testPropertyFiles_MainAndExtra() throws Exception {
 
         // setVariableValueToObject(mojo,"encoding","UTF-8");
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", filterList);
         setVariableValueToObject(mojo, "filters", extraFilterList);
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
@@ -506,38 +494,36 @@ public void testPropertyFiles_MainAndExtra() throws Exception {
         String resourcesDir = project.getOutputDirectory();
         String checkString = "current working directory=testdir; old working directory=testdir2";
 
-        File file = new File(resourcesDir, "main-extra.properties");
-        assertContent(file.getAbsolutePath(), checkString);
+        Path file = Paths.get(resourcesDir, "main-extra.properties");
+        assertContent(file.toAbsolutePath().toString(), checkString);
     }
 
     /**
      * Validates that a Filter token containing a project property will be resolved before the Filter is applied to the
      * resources.
      *
-     * @throws Exception
      */
-    public void testPropertyFiles_Filtering_TokensInFilters() throws Exception {
-        final File testPom = new File(getBasedir(), defaultPomFilePath);
-        final ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        final MavenProjectResourcesStub project =
-                new MavenProjectResourcesStub("resourcePropertyFiles_Filtering_TokensInFilters");
-        final List<Resource> resources = project.getBuild().getResources();
-        final LinkedList<String> filterList = new LinkedList<>();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testPropertyFiles_Filtering_TokensInFilters(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
+        LinkedList<String> filterList = new LinkedList<>();
+
         project.addFile("file4.properties", "current working directory=${filter.token}");
         project.addFile("filter.properties", "filter.token=${pom-property}");
-        project.setResourceFiltering(0, true);
+        project.setResourceFiltering(true);
         project.addProperty("pom-property", "foobar");
         project.setupBuildEnvironment();
         filterList.add(project.getResourcesDirectory() + "filter.properties");
 
         // setVariableValueToObject(mojo,"encoding","UTF-8");
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", filterList);
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
@@ -548,27 +534,26 @@ public void testPropertyFiles_Filtering_TokensInFilters() throws Exception {
         assertContent(resourcesDir + "/file4.properties", checkString);
     }
 
-    public void testWindowsPathEscapingDisabled() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("windows-paths");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testWindowsPathEscapingDisabled(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
-        project.getProperties().setProperty("basePath", "C:\\Users\\Administrator");
-        project.getProperties().setProperty("docsPath", "${basePath}\\Documents");
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
+        project.addProperty("basePath", "C:\\Users\\Administrator");
+        project.addProperty("docsPath", "${basePath}\\Documents");
 
         project.addFile("path-listing.txt", "base path is ${basePath}\ndocuments path is ${docsPath}");
-        project.setResourceFiltering(0, true);
+        project.setResourceFiltering(true);
 
         project.cleanBuildEnvironment();
         project.setupBuildEnvironment();
 
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         setVariableValueToObject(mojo, "escapeWindowsPaths", Boolean.FALSE);
@@ -577,34 +562,33 @@ public void testWindowsPathEscapingDisabled() throws Exception {
 
         String resourcesDir = project.getOutputDirectory();
 
-        assertTrue(FileUtils.fileExists(new File(resourcesDir, "path-listing.txt").getAbsolutePath()));
+        assertTrue(Files.exists(Paths.get(resourcesDir, "path-listing.txt").toAbsolutePath()));
 
         assertEquals(
                 "base path is C:\\Users\\Administrator\ndocuments path is C:\\Users\\Administrator\\Documents",
-                FileUtils.fileRead(new File(resourcesDir, "path-listing.txt")));
+                new String(Files.readAllBytes(Paths.get(resourcesDir, "path-listing.txt"))));
     }
 
-    public void testWindowsPathEscapingEnabled() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("resources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("windows-paths");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "resources", pom = CONFIG_XML)
+    @Basedir
+    public void testWindowsPathEscapingEnabled(ResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
-        project.getProperties().setProperty("basePath", "C:\\Users\\Administrator");
-        project.getProperties().setProperty("docsPath", "${basePath}\\Documents");
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
+        project.addProperty("basePath", "C:\\Users\\Administrator");
+        project.addProperty("docsPath", "${basePath}\\Documents");
 
         project.addFile("path-listing.txt", "base path is ${basePath}\ndocuments path is ${docsPath}");
-        project.setResourceFiltering(0, true);
+        project.setResourceFiltering(true);
 
         project.cleanBuildEnvironment();
         project.setupBuildEnvironment();
 
         setVariableValueToObject(mojo, "project", project);
-        setVariableValueToObject(mojo, "resources", resources);
-        setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
+        setVariableValueToObject(mojo, "resources", getResources(project));
+        setVariableValueToObject(mojo, "outputDirectory", Paths.get(project.getOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
 
@@ -614,20 +598,42 @@ public void testWindowsPathEscapingEnabled() throws Exception {
 
         String resourcesDir = project.getOutputDirectory();
 
-        assertTrue(FileUtils.fileExists(new File(resourcesDir, "path-listing.txt").getAbsolutePath()));
+        assertTrue(Files.exists(Paths.get(resourcesDir, "path-listing.txt").toAbsolutePath()));
 
         assertEquals(
                 "base path is C:\\\\Users\\\\Administrator\ndocuments path is C:\\\\Users\\\\Administrator\\\\Documents",
-                FileUtils.fileRead(new File(resourcesDir, "path-listing.txt")));
+                new String(Files.readAllBytes(Paths.get(resourcesDir, "path-listing.txt"))));
     }
 
     /**
      * Ensures the file exists and its first line equals the given data.
      */
     private void assertContent(String fileName, String data) throws IOException {
-        assertTrue(FileUtils.fileExists(fileName));
-        try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
+        assertTrue(Files.exists(Paths.get(fileName)));
+        try (BufferedReader reader = Files.newBufferedReader(Paths.get(fileName))) {
             assertEquals(data, reader.readLine());
         }
     }
+
+    private static final String LOCAL_REPO = "/target/local-repo";
+
+    @Provides
+    @Singleton
+    @SuppressWarnings("unused")
+    private static InternalSession getMockSession() {
+        return SessionMock.getMockSession(getBasedir() + LOCAL_REPO);
+    }
+
+    @Provides
+    @Singleton
+    @SuppressWarnings("unused")
+    private static Project createProject() throws Exception {
+        return new MavenProjectResourcesStub();
+    }
+
+    private List<Resource> getResources(MavenProjectResourcesStub project) {
+        return project.getBuild().getResources().stream()
+                .map(ResourceUtils::newResource)
+                .collect(Collectors.toList());
+    }
 }
diff --git a/src/test/java/org/apache/maven/plugins/resources/TestResourcesTest.java b/src/test/java/org/apache/maven/plugins/resources/TestResourcesTest.java
index 13acc44..345bd14 100644
--- a/src/test/java/org/apache/maven/plugins/resources/TestResourcesTest.java
+++ b/src/test/java/org/apache/maven/plugins/resources/TestResourcesTest.java
@@ -18,45 +18,55 @@
  */
 package org.apache.maven.plugins.resources;
 
-import java.io.File;
+import java.nio.file.Paths;
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
-import org.apache.maven.model.Resource;
-import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import org.apache.maven.api.Project;
+import org.apache.maven.api.di.Provides;
+import org.apache.maven.api.di.Singleton;
+import org.apache.maven.api.plugin.testing.Basedir;
+import org.apache.maven.api.plugin.testing.InjectMojo;
+import org.apache.maven.api.plugin.testing.MojoTest;
+import org.apache.maven.api.plugin.testing.stubs.SessionMock;
+import org.apache.maven.internal.impl.InternalSession;
 import org.apache.maven.plugins.resources.stub.MavenProjectResourcesStub;
+import org.apache.maven.shared.filtering.Resource;
 import org.codehaus.plexus.util.FileUtils;
+import org.junit.jupiter.api.Test;
 
-public class TestResourcesTest extends AbstractMojoTestCase {
-    protected static final String defaultPomFilePath = "/target/test-classes/unit/resources-test/plugin-config.xml";
+import static org.apache.maven.api.plugin.testing.MojoExtension.getBasedir;
+import static org.apache.maven.api.plugin.testing.MojoExtension.setVariableValueToObject;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
+@MojoTest
+public class TestResourcesTest {
+    private static final String CONFIG_XML = "classpath:/unit/resources-test/plugin-config.xml";
 
     /**
      * test mojo lookup, test harness should be working fine
-     *
-     * @throws Exception
      */
-    public void testHarnessEnvironment() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        ResourcesMojo mojo = (ResourcesMojo) lookupMojo("testResources", testPom);
-
+    @Test
+    @InjectMojo(goal = "testResources", pom = CONFIG_XML)
+    @Basedir
+    public void testHarnessEnvironment(TestResourcesMojo mojo) {
         assertNotNull(mojo);
     }
 
     /**
-     * @throws Exception
      */
-    public void testTestResourceDirectoryCreation() throws Exception {
-        File testPom = new File(getBasedir(), defaultPomFilePath);
-        TestResourcesMojo mojo = (TestResourcesMojo) lookupMojo("testResources", testPom);
-        MavenProjectResourcesStub project = new MavenProjectResourcesStub("testResourceDirectoryStructure");
-        List<Resource> resources = project.getBuild().getResources();
-
+    @Test
+    @InjectMojo(goal = "testResources", pom = CONFIG_XML)
+    @Basedir
+    public void testTestResourceDirectoryCreation(TestResourcesMojo mojo) throws Exception {
         assertNotNull(mojo);
 
+        MavenProjectResourcesStub project = (MavenProjectResourcesStub) mojo.project;
+
+        List<Resource> resources = getResources(project);
+
         project.addFile("file4.txt");
         project.addFile("package/file3.nottest");
         project.addFile("notpackage/file1.include");
@@ -67,17 +77,39 @@ public void testTestResourceDirectoryCreation() throws Exception {
         setVariableValueToObject(mojo, "project", project);
         setVariableValueToObject(mojo, "resources", resources);
         setVariableValueToObject(
-                mojo, "outputDirectory", new File(project.getBuild().getTestOutputDirectory()));
+                mojo, "outputDirectory", Paths.get(project.getBuild().getTestOutputDirectory()));
         setVariableValueToObject(mojo, "buildFilters", Collections.emptyList());
         setVariableValueToObject(mojo, "useBuildFilters", Boolean.TRUE);
         mojo.execute();
 
-        String resorucesDir = project.getTestOutputDirectory();
+        String resourcesDir = project.getTestOutputDirectory();
+
+        assertTrue(FileUtils.fileExists(resourcesDir + "/file4.txt"));
+        assertTrue(FileUtils.fileExists(resourcesDir + "/package/file3.nottest"));
+        assertTrue(FileUtils.fileExists(resourcesDir + "/notpackage/file1.include"));
+        assertTrue(FileUtils.fileExists(resourcesDir + "/package/test"));
+        assertTrue(FileUtils.fileExists(resourcesDir + "/notpackage/test"));
+    }
+
+    private static final String LOCAL_REPO = "/target/local-repo";
+
+    @Provides
+    @Singleton
+    @SuppressWarnings("unused")
+    private static InternalSession getMockSession() {
+        return SessionMock.getMockSession(getBasedir() + LOCAL_REPO);
+    }
+
+    @Provides
+    @Singleton
+    @SuppressWarnings("unused")
+    private static Project createProject() throws Exception {
+        return new MavenProjectResourcesStub();
+    }
 
-        assertTrue(FileUtils.fileExists(resorucesDir + "/file4.txt"));
-        assertTrue(FileUtils.fileExists(resorucesDir + "/package/file3.nottest"));
-        assertTrue(FileUtils.fileExists(resorucesDir + "/notpackage/file1.include"));
-        assertTrue(FileUtils.fileExists(resorucesDir + "/package/test"));
-        assertTrue(FileUtils.fileExists(resorucesDir + "/notpackage/test"));
+    private List<Resource> getResources(MavenProjectResourcesStub project) {
+        return project.getBuild().getResources().stream()
+                .map(ResourceUtils::newResource)
+                .collect(Collectors.toList());
     }
 }
diff --git a/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectBasicStub.java b/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectBasicStub.java
index adb6d88..e2acdf9 100644
--- a/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectBasicStub.java
+++ b/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectBasicStub.java
@@ -18,14 +18,14 @@
  */
 package org.apache.maven.plugins.resources.stub;
 
-import java.io.File;
+import java.nio.file.Paths;
 import java.util.Properties;
 
-import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
-import org.codehaus.plexus.PlexusTestCase;
+import org.apache.maven.api.plugin.testing.stubs.ProjectStub;
+import org.codehaus.plexus.testing.PlexusExtension;
 import org.codehaus.plexus.util.FileUtils;
 
-public class MavenProjectBasicStub extends MavenProjectStub {
+public class MavenProjectBasicStub extends ProjectStub {
     protected String identifier;
 
     protected String testRootDir;
@@ -37,56 +37,18 @@ public class MavenProjectBasicStub extends MavenProjectStub {
     public MavenProjectBasicStub(String id) {
         properties = new Properties();
         identifier = id;
-        testRootDir = PlexusTestCase.getBasedir() + "/target/unit/test-dir/" + identifier;
+        testRootDir = PlexusExtension.getBasedir() + "/target/test-classes/unit/test-dir/" + identifier;
+        setBasedir(Paths.get(testRootDir));
 
         if (!FileUtils.fileExists(testRootDir)) {
             FileUtils.mkdir(testRootDir);
         }
-    }
-
-    public String getName() {
-        return "Test Project " + identifier;
-    }
-
-    public void setDescription(String desc) {
-        description = desc;
-    }
-
-    public String getDescription() {
-        if (description == null) {
-            return "this is a test project";
-        } else {
-            return description;
-        }
-    }
-
-    public File getBasedir() {
-        // create an isolated environment
-        // see setupTestEnvironment for details
-        return new File(testRootDir);
-    }
-
-    public String getGroupId() {
-        return "org.apache.maven.plugin.test";
-    }
-
-    public String getArtifactId() {
-        return "maven-resource-plugin-test#" + identifier;
-    }
-
-    public String getPackaging() {
-        return "org.apache.maven.plugin.test";
-    }
-
-    public String getVersion() {
-        return identifier;
-    }
-
-    public void addProperty(String key, String value) {
-        properties.put(key, value);
-    }
 
-    public Properties getProperties() {
-        return properties;
+        setName("Test Project " + identifier);
+        setGroupId("org.apache.maven.plugin.test");
+        setArtifactId("maven-resource-plugin-test#" + identifier);
+        setVersion(identifier);
+        setPackaging("org.apache.maven.plugin.test");
+        setDescription("this is a test project");
     }
 }
diff --git a/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectBuildStub.java b/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectBuildStub.java
index 490fcc9..c1ea7f2 100644
--- a/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectBuildStub.java
+++ b/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectBuildStub.java
@@ -18,18 +18,35 @@
  */
 package org.apache.maven.plugins.resources.stub;
 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.HashMap;
 
-import org.apache.maven.model.Build;
 import org.codehaus.plexus.util.FileUtils;
 
 public class MavenProjectBuildStub extends MavenProjectBasicStub {
-    protected Build build;
-
     protected String srcDirectory;
 
     protected String targetDirectory;
@@ -57,7 +74,6 @@ public class MavenProjectBuildStub extends MavenProjectBasicStub {
     public MavenProjectBuildStub(String key) throws Exception {
         super(key);
 
-        build = new Build();
         fileList = new ArrayList<>();
         directoryList = new ArrayList<>();
         dataMap = new HashMap<>();
@@ -72,7 +88,7 @@ public void addDirectory(String name) {
 
     public void setOutputDirectory(String dir) {
         outputDirectory = buildDirectory + "/" + dir;
-        build.setOutputDirectory(outputDirectory);
+        setModel(getModel().withBuild(getModel().getBuild().withOutputDirectory(outputDirectory)));
     }
 
     public void addFile(String name) {
@@ -104,10 +120,6 @@ public String getTestResourcesDirectory() {
         return testResourcesDirectory;
     }
 
-    public Build getBuild() {
-        return build;
-    }
-
     /**
      * returns true if the path is relative
      * and false if absolute
@@ -138,9 +150,12 @@ private void setupBuild() {
         resourcesDirectory = srcDirectory + "/main/resources/";
         testResourcesDirectory = srcDirectory + "/test/resources/";
 
-        build.setDirectory(buildDirectory);
-        build.setOutputDirectory(outputDirectory);
-        build.setTestOutputDirectory(testOutputDirectory);
+        setModel(getModel()
+                .withBuild(org.apache.maven.api.model.Build.newBuilder()
+                        .directory(buildDirectory)
+                        .outputDirectory(outputDirectory)
+                        .testOutputDirectory(testOutputDirectory)
+                        .build()));
     }
 
     public void cleanBuildEnvironment() throws Exception {
@@ -186,67 +201,30 @@ public void setupBuildEnvironment() throws Exception {
         }
     }
 
-    private void createDirectories(String parent, String testparent) {
-        File currentDirectory;
-
+    private void createDirectories(String parent, String testparent) throws IOException {
         for (String directory : directoryList) {
-            currentDirectory = new File(parent, "/" + directory);
-
-            if (!currentDirectory.exists()) {
-                currentDirectory.mkdirs();
-            }
-
-            // duplicate dir structure in test resources
-            currentDirectory = new File(testparent, "/" + directory);
-
-            if (!currentDirectory.exists()) {
-                currentDirectory.mkdirs();
-            }
+            Files.createDirectories(new File(parent, "/" + directory).toPath());
+            Files.createDirectories(new File(testparent, "/" + directory).toPath());
         }
     }
 
     private void createFiles(String parent, String testparent) throws IOException {
-        File currentFile;
-
         for (String file : fileList) {
-            currentFile = new File(parent, file);
-
-            // create the necessary parent directories
-            // before we create the files
-            if (!currentFile.getParentFile().exists()) {
-                currentFile.getParentFile().mkdirs();
-            }
-
-            if (!currentFile.exists()) {
-                try {
-                    currentFile.createNewFile();
-                    populateFile(currentFile);
-                } catch (IOException io) {
-                    // TODO: handle exception
-                }
-            }
-
-            // duplicate file in test resources
-            currentFile = new File(testparent, file);
-
-            if (!currentFile.getParentFile().exists()) {
-                currentFile.getParentFile().mkdirs();
-            }
-
-            if (!currentFile.exists()) {
-                currentFile.createNewFile();
-                populateFile(currentFile);
-            }
+            populateFile(new File(parent, file));
+            populateFile(new File(testparent, file));
         }
     }
 
     private void populateFile(File file) throws IOException {
+        Files.createDirectories(file.getParentFile().toPath());
         String data = dataMap.get(file.getName());
-
-        if ((data != null) && file.exists()) {
-            try (FileOutputStream outputStream = new FileOutputStream(file)) {
+        try (FileOutputStream outputStream = new FileOutputStream(file)) {
+            if (data != null) {
                 outputStream.write(data.getBytes());
             }
         }
+        if (!file.exists()) {
+            throw new IOException("Unable to create file: " + file);
+        }
     }
 }
diff --git a/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectResourcesStub.java b/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectResourcesStub.java
index e0c5420..a6699b9 100644
--- a/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectResourcesStub.java
+++ b/src/test/java/org/apache/maven/plugins/resources/stub/MavenProjectResourcesStub.java
@@ -18,56 +18,103 @@
  */
 package org.apache.maven.plugins.resources.stub;
 
-import java.io.File;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+import java.util.function.Function;
 
+import org.apache.maven.api.model.Build;
+import org.apache.maven.api.plugin.testing.MojoExtension;
 import org.apache.maven.model.Resource;
+import org.codehaus.plexus.util.FileUtils;
 
 public class MavenProjectResourcesStub extends MavenProjectBuildStub {
 
-    private File baseDir;
-
-    public MavenProjectResourcesStub(String id) throws Exception {
-        super(id);
+    public MavenProjectResourcesStub() throws Exception {
+        super(MojoExtension.getTestId());
         setupResources();
         setupTestResources();
+        Path outputDirectory = Paths.get(getOutputDirectory());
+        FileUtils.deleteDirectory(outputDirectory.toFile());
+        Files.createDirectories(outputDirectory);
     }
 
     public void addInclude(String pattern) {
-        build.getResources().get(0).addInclude(pattern);
+        withResource(r -> r.withIncludes(concat(r.getIncludes(), pattern)));
     }
 
     public void addExclude(String pattern) {
-        build.getResources().get(0).addExclude(pattern);
+        withResource(r -> r.withExcludes(concat(r.getExcludes(), pattern)));
     }
 
     public void addTestInclude(String pattern) {
-        build.getTestResources().get(0).addInclude(pattern);
+        withTestResource(r -> r.withIncludes(concat(r.getIncludes(), pattern)));
     }
 
     public void addTestExclude(String pattern) {
-        build.getTestResources().get(0).addExclude(pattern);
+        withTestResource(r -> r.withExcludes(concat(r.getExcludes(), pattern)));
     }
 
     public void setTargetPath(String path) {
-        build.getResources().get(0).setTargetPath(path);
+        withResource(r -> r.withTargetPath(path));
     }
 
     public void setTestTargetPath(String path) {
-        build.getTestResources().get(0).setTargetPath(path);
+        withTestResource(r -> r.withTargetPath(path));
     }
 
     public void setDirectory(String dir) {
-        build.getResources().get(0).setDirectory(dir);
+        withResource(r -> r.withDirectory(dir));
     }
 
     public void setTestDirectory(String dir) {
-        build.getTestResources().get(0).setDirectory(dir);
+        withTestResource(r -> r.withDirectory(dir));
+    }
+
+    public void setResourceFiltering(boolean filter) {
+        withResource(r -> r.withFiltering(Boolean.toString(filter)));
+    }
+
+    private <T> List<T> concat(Collection<T> collection, T item) {
+        List<T> list = new ArrayList<>(collection);
+        list.add(item);
+        return list;
+    }
+
+    private void withResource(
+            Function<org.apache.maven.api.model.Resource, org.apache.maven.api.model.Resource> mapper) {
+        Build build = getModel().getBuild();
+        setModel(getModel()
+                .withBuild(build.withResources(Collections.singletonList(
+                        mapper.apply(build.getResources().get(0))))));
     }
 
-    public void setResourceFiltering(int nIndex, boolean filter) {
-        if (build.getResources().size() > nIndex) {
-            build.getResources().get(nIndex).setFiltering(filter);
-        }
+    private void withTestResource(
+            Function<org.apache.maven.api.model.Resource, org.apache.maven.api.model.Resource> mapper) {
+        Build build = getModel().getBuild();
+        setModel(getModel()
+                .withBuild(build.withTestResources(Collections.singletonList(
+                        mapper.apply(build.getTestResources().get(0))))));
     }
 
     private void setupResources() {
@@ -77,10 +124,13 @@ private void setupResources() {
         // of getBasedir
 
         // setup default resources
-        resource.setDirectory(getBasedir().getPath() + "/src/main/resources");
+        resource.setDirectory(testRootDir + "/src/main/resources");
         resource.setFiltering(false);
         resource.setTargetPath(null);
-        build.addResource(resource);
+        setModel(getModel()
+                .withBuild(getModel()
+                        .getBuild()
+                        .withResources(concat(getModel().getBuild().getResources(), resource.getDelegate()))));
     }
 
     private void setupTestResources() {
@@ -90,17 +140,20 @@ private void setupTestResources() {
         // of getBasedir
 
         // setup default test resources
-        resource.setDirectory(getBasedir().getPath() + "/src/test/resources");
+        resource.setDirectory(testRootDir + "/src/test/resources");
         resource.setFiltering(false);
         resource.setTargetPath(null);
-        build.addTestResource(resource);
+        setModel(getModel()
+                .withBuild(getModel()
+                        .getBuild()
+                        .withTestResources(concat(getModel().getBuild().getTestResources(), resource.getDelegate()))));
     }
 
-    public File getBaseDir() {
-        return baseDir == null ? super.getBasedir() : baseDir;
+    public String getOutputDirectory() {
+        return getBuild().getOutputDirectory();
     }
 
-    public void setBaseDir(File baseDir) {
-        this.baseDir = baseDir;
+    public String getTestOutputDirectory() {
+        return getBuild().getTestOutputDirectory();
     }
 }
diff --git a/src/test/resources/unit/resources-test/plugin-config.xml b/src/test/resources/unit/resources-test/plugin-config.xml
index 3f1dc4c..43d2bd7 100644
--- a/src/test/resources/unit/resources-test/plugin-config.xml
+++ b/src/test/resources/unit/resources-test/plugin-config.xml
@@ -25,7 +25,10 @@
       <plugin>
         <artifactId>maven-resources-plugin</artifactId>
         <configuration>
-          <outputDirectory>/test-classes/unit/resources-test</outputDirectory>
+<!--          <project implementation="org.apache.maven.api.plugin.testing.stubs.ProjectStub">-->
+<!--            <pomPath>${basedir}/src/test/resources/unit/resources-test/plugin-config.xml</pomPath>-->
+<!--          </project>-->
+<!--          <outputDirectory>/test-classes/unit/resources-test</outputDirectory>-->
           <encoding>UTF-8</encoding>
         </configuration>
       </plugin>
@@ -35,12 +38,12 @@
         <filtering>false</filtering>
         <directory>/test/resources/unit/test-dir</directory>
         <includes>
-          **/*.include
-          **/*.test
+          <include>**/*.include</include>
+          <include>**/*.test</include>
         </includes>
         <excludes>
-          **/**.exclude
-          **/*.nottest
+          <exclude>**/**.exclude</exclude>
+          <exclude>**/*.nottest</exclude>
         </excludes>
       </resource>
     </resources>