You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sl...@apache.org on 2026/10/13 21:50:21 UTC

(maven-dependency-plugin) 01/01: [MDEP-758] Skip test scoped unused dependencies with maven.test.skip, tolerate unneeded forced usage, add analyze-report-only

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

slachiewicz pushed a commit to branch agent/analyze-test-skip-report-only
in repository https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git

commit 2490af6a86e3db1ee4ee278ec2ddddcca680ba1f
Author: Sylwester Lachiewicz <sl...@apache.org>
AuthorDate: Tue Oct 13 23:48:00 2026 +0200

    [MDEP-758] Skip test scoped unused dependencies with maven.test.skip, tolerate unneeded forced usage, add analyze-report-only
    
    Also covers MDEP-973 and MDEP-879.
    
    AnalyzeReportOnly overrides the inherited @Execute with LifecyclePhase.NONE.
    Without it the generated descriptor gives analyze-report-only the same
    test-compile executePhase as analyze-report, because plugin-tools inherits
    class-level @Execute from the superclass.
---
 .../invoker.properties                             | 18 +++++
 .../pom.xml                                        | 62 +++++++++++++++
 .../src/main/java/Main.java                        | 25 ++++++
 .../verify.groovy                                  | 26 ++++++
 .../invoker.properties                             | 18 +++++
 .../pom.xml                                        | 62 +++++++++++++++
 .../src/main/java/Main.java                        | 25 ++++++
 .../verify.groovy                                  | 27 +++++++
 .../invoker.properties                             | 18 +++++
 .../projects/analyze-report-only-mdep-879/pom.xml  | 57 ++++++++++++++
 .../src/main/java/Main.java                        | 25 ++++++
 .../src/test/java/MainTest.java                    | 23 ++++++
 .../analyze-report-only-mdep-879/verify.groovy     | 27 +++++++
 .../analyze-test-skip-mdep-758/invoker.properties  | 18 +++++
 src/it/projects/analyze-test-skip-mdep-758/pom.xml | 67 ++++++++++++++++
 .../src/main/java/Main.java                        | 23 ++++++
 .../analyze-test-skip-mdep-758/verify.groovy       | 31 ++++++++
 .../dependency/analyze/AbstractAnalyzeMojo.java    | 32 +++++++-
 .../plugins/dependency/analyze/AnalyzeReport.java  |  6 +-
 .../dependency/analyze/AnalyzeReportOnly.java      | 47 +++++++++++
 .../plugins/dependency/analyze/ForcedUsage.java    | 74 +++++++++++++++++
 src/site/markdown/index.md                         |  1 +
 src/site/markdown/usage.md.vm                      |  6 ++
 .../analyze/AbstractAnalyzeMojoTest.java           | 92 +++++++++++++++++++++-
 24 files changed, 807 insertions(+), 3 deletions(-)

diff --git a/src/it/projects/analyze-forced-usage-already-used-mdep-973/invoker.properties b/src/it/projects/analyze-forced-usage-already-used-mdep-973/invoker.properties
new file mode 100644
index 00000000..e6028302
--- /dev/null
+++ b/src/it/projects/analyze-forced-usage-already-used-mdep-973/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+
+invoker.goals = clean ${project.groupId}:${project.artifactId}:${project.version}:analyze
diff --git a/src/it/projects/analyze-forced-usage-already-used-mdep-973/pom.xml b/src/it/projects/analyze-forced-usage-already-used-mdep-973/pom.xml
new file mode 100644
index 00000000..ed2ec84d
--- /dev/null
+++ b/src/it/projects/analyze-forced-usage-already-used-mdep-973/pom.xml
@@ -0,0 +1,62 @@
+<?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/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.dependency</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <name>Test</name>
+  <description>
+    Test that forcing the usage of an already used dependency is a warning (MDEP-973)
+  </description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-model</artifactId>
+      <version>3.9.16</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-dependency-plugin</artifactId>
+          <version>@project.version@</version>
+          <configuration>
+            <usedDependencies>
+              <usedDependency>org.apache.maven:maven-model</usedDependency>
+            </usedDependencies>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/src/it/projects/analyze-forced-usage-already-used-mdep-973/src/main/java/Main.java b/src/it/projects/analyze-forced-usage-already-used-mdep-973/src/main/java/Main.java
new file mode 100644
index 00000000..967d85f3
--- /dev/null
+++ b/src/it/projects/analyze-forced-usage-already-used-mdep-973/src/main/java/Main.java
@@ -0,0 +1,25 @@
+/*
+ * 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 org.apache.maven.model.Model;
+
+public class Main
+{
+    public Model model = null;
+}
diff --git a/src/it/projects/analyze-forced-usage-already-used-mdep-973/verify.groovy b/src/it/projects/analyze-forced-usage-already-used-mdep-973/verify.groovy
new file mode 100644
index 00000000..01b1fabc
--- /dev/null
+++ b/src/it/projects/analyze-forced-usage-already-used-mdep-973/verify.groovy
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+String log = new File( basedir, "build.log" ).getText( "UTF-8" );
+
+assert log.contains( "Unneeded forced usage of org.apache.maven:maven-model" ) :
+    "expected a warning about the unneeded forced usage";
+assert !log.contains( "Cannot analyze dependencies" ) : "the analysis must not fail";
+
+return true;
diff --git a/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/invoker.properties b/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/invoker.properties
new file mode 100644
index 00000000..ab68bf1c
--- /dev/null
+++ b/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+
+invoker.goals = clean ${project.groupId}:${project.artifactId}:${project.version}:analyze-report
diff --git a/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/pom.xml b/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/pom.xml
new file mode 100644
index 00000000..bcb28b0a
--- /dev/null
+++ b/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/pom.xml
@@ -0,0 +1,62 @@
+<?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/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.dependency</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <name>Test</name>
+  <description>
+    Test that analyze-report survives forcing the usage of an already used dependency (MDEP-973)
+  </description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-model</artifactId>
+      <version>3.9.16</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-dependency-plugin</artifactId>
+          <version>@project.version@</version>
+          <configuration>
+            <usedDependencies>
+              <usedDependency>org.apache.maven:maven-model</usedDependency>
+            </usedDependencies>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/src/main/java/Main.java b/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/src/main/java/Main.java
new file mode 100644
index 00000000..967d85f3
--- /dev/null
+++ b/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/src/main/java/Main.java
@@ -0,0 +1,25 @@
+/*
+ * 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 org.apache.maven.model.Model;
+
+public class Main
+{
+    public Model model = null;
+}
diff --git a/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/verify.groovy b/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/verify.groovy
new file mode 100644
index 00000000..29b9d0b4
--- /dev/null
+++ b/src/it/projects/analyze-report-forced-usage-already-used-mdep-973/verify.groovy
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+File htmlFile = new File( basedir, "target/reports/dependency-analysis.html" );
+assert htmlFile.isFile() && htmlFile.length() > 0 : "Dependency analysis report missing " + htmlFile;
+
+String log = new File( basedir, "build.log" ).getText( "UTF-8" );
+assert log.contains( "Unneeded forced usage of org.apache.maven:maven-model" ) :
+    "expected a warning about the unneeded forced usage";
+
+return true;
diff --git a/src/it/projects/analyze-report-only-mdep-879/invoker.properties b/src/it/projects/analyze-report-only-mdep-879/invoker.properties
new file mode 100644
index 00000000..139e6319
--- /dev/null
+++ b/src/it/projects/analyze-report-only-mdep-879/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+
+invoker.goals = clean compile ${project.groupId}:${project.artifactId}:${project.version}:analyze-report-only
diff --git a/src/it/projects/analyze-report-only-mdep-879/pom.xml b/src/it/projects/analyze-report-only-mdep-879/pom.xml
new file mode 100644
index 00000000..54318727
--- /dev/null
+++ b/src/it/projects/analyze-report-only-mdep-879/pom.xml
@@ -0,0 +1,57 @@
+<?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/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.dependency</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <name>Test</name>
+  <description>
+    Test that analyze-report-only does not fork test-compile (MDEP-879)
+  </description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-model</artifactId>
+      <version>3.9.16</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-dependency-plugin</artifactId>
+          <version>@project.version@</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/src/it/projects/analyze-report-only-mdep-879/src/main/java/Main.java b/src/it/projects/analyze-report-only-mdep-879/src/main/java/Main.java
new file mode 100644
index 00000000..967d85f3
--- /dev/null
+++ b/src/it/projects/analyze-report-only-mdep-879/src/main/java/Main.java
@@ -0,0 +1,25 @@
+/*
+ * 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 org.apache.maven.model.Model;
+
+public class Main
+{
+    public Model model = null;
+}
diff --git a/src/it/projects/analyze-report-only-mdep-879/src/test/java/MainTest.java b/src/it/projects/analyze-report-only-mdep-879/src/test/java/MainTest.java
new file mode 100644
index 00000000..069bf121
--- /dev/null
+++ b/src/it/projects/analyze-report-only-mdep-879/src/test/java/MainTest.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+
+public class MainTest
+{
+}
diff --git a/src/it/projects/analyze-report-only-mdep-879/verify.groovy b/src/it/projects/analyze-report-only-mdep-879/verify.groovy
new file mode 100644
index 00000000..a448cf7e
--- /dev/null
+++ b/src/it/projects/analyze-report-only-mdep-879/verify.groovy
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+File htmlFile = new File( basedir, "target/reports/dependency-analysis.html" );
+assert htmlFile.isFile() && htmlFile.length() > 0 : "Dependency analysis report missing " + htmlFile;
+
+String log = new File( basedir, "build.log" ).getText( "UTF-8" );
+assert log.contains( ":compile (default-compile)" ) : "expected the explicitly requested compile phase to run";
+assert !log.contains( ":testCompile (default-testCompile)" ) : "analyze-report-only must not fork test-compile";
+
+return true;
diff --git a/src/it/projects/analyze-test-skip-mdep-758/invoker.properties b/src/it/projects/analyze-test-skip-mdep-758/invoker.properties
new file mode 100644
index 00000000..5c72f8a2
--- /dev/null
+++ b/src/it/projects/analyze-test-skip-mdep-758/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+
+invoker.goals = clean ${project.groupId}:${project.artifactId}:${project.version}:analyze -Dmaven.test.skip=true
diff --git a/src/it/projects/analyze-test-skip-mdep-758/pom.xml b/src/it/projects/analyze-test-skip-mdep-758/pom.xml
new file mode 100644
index 00000000..69f1517e
--- /dev/null
+++ b/src/it/projects/analyze-test-skip-mdep-758/pom.xml
@@ -0,0 +1,67 @@
+<?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/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.dependency</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <name>Test</name>
+  <description>
+    Test that test scoped dependencies are not reported as unused when maven.test.skip is set (MDEP-758)
+  </description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.its.dependency</groupId>
+      <artifactId>scope-leaf</artifactId>
+      <version>1.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.its.dependency</groupId>
+      <artifactId>scope-root</artifactId>
+      <version>1.0</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-dependency-plugin</artifactId>
+          <version>@project.version@</version>
+          <configuration>
+            <verbose>true</verbose>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/src/it/projects/analyze-test-skip-mdep-758/src/main/java/Main.java b/src/it/projects/analyze-test-skip-mdep-758/src/main/java/Main.java
new file mode 100644
index 00000000..5e405ff1
--- /dev/null
+++ b/src/it/projects/analyze-test-skip-mdep-758/src/main/java/Main.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+
+public class Main
+{
+}
diff --git a/src/it/projects/analyze-test-skip-mdep-758/verify.groovy b/src/it/projects/analyze-test-skip-mdep-758/verify.groovy
new file mode 100644
index 00000000..542c847d
--- /dev/null
+++ b/src/it/projects/analyze-test-skip-mdep-758/verify.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+String log = new File( basedir, "build.log" ).getText( "UTF-8" );
+
+int unused = log.indexOf( "Unused declared dependencies found:" );
+assert unused >= 0 : "expected an unused declared dependencies warning in build.log";
+String report = log.substring( unused );
+assert report.contains( "org.apache.maven.its.dependency:scope-root:jar:1.0:provided" ) :
+    "the provided scoped dependency must still be reported";
+assert !report.contains( "org.apache.maven.its.dependency:scope-leaf:jar:1.0:test" ) :
+    "the test scoped dependency must not be reported when maven.test.skip is set";
+assert log.contains( "maven.test.skip is set" ) : "expected the info line explaining why";
+
+return true;
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
index f5758f55..9c577138 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
@@ -20,6 +20,7 @@ package org.apache.maven.plugins.dependency.analyze;
 
 import java.io.File;
 import java.io.StringWriter;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
@@ -158,6 +159,16 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
     @Parameter(property = "mdep.analyze.skip", defaultValue = "false")
     private boolean skip;
 
+    /**
+     * Whether test compilation is skipped, as set by <code>maven.test.skip</code>. When <code>true</code>, test scoped
+     * dependencies are left out of the "declared but unused" list, because no test class is analyzed. Dependencies of
+     * other scopes are still analyzed.
+     *
+     * @since 3.12.0
+     */
+    @Parameter(property = "maven.test.skip", defaultValue = "false", readonly = true)
+    private boolean testSkip;
+
     /**
      * List of dependencies that will be ignored. Any dependency on this list will be excluded from the "declared but
      * unused", the "used but undeclared", and the "non-test scoped" list. The filter syntax is:
@@ -329,11 +340,16 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
 
     private boolean checkDependencies() throws MojoExecutionException {
         ProjectDependencyAnalysis analysis;
+        List<String> unneededForcedUsage = Collections.emptyList();
         try {
             analysis = createProjectDependencyAnalyzer().analyze(project, excludedClasses);
 
             if (usedDependencies != null) {
-                analysis = analysis.forceDeclaredDependenciesUsage(usedDependencies);
+                ForcedUsage forced = new ForcedUsage(analysis, usedDependencies);
+                unneededForcedUsage = forced.getUnneeded();
+                if (forced.getToForce().length > 0) {
+                    analysis = analysis.forceDeclaredDependenciesUsage(forced.getToForce());
+                }
             }
         } catch (ProjectDependencyAnalyzerException exception) {
             throw new MojoExecutionException("Cannot analyze dependencies", exception);
@@ -353,6 +369,14 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
         Set<Artifact> ignoredUnusedDeclared = new LinkedHashSet<>();
         Set<Artifact> ignoredNonTestScope = new LinkedHashSet<>();
 
+        if (testSkip) {
+            int before = unusedDeclared.size();
+            unusedDeclared.removeIf(artifact -> Artifact.SCOPE_TEST.equals(artifact.getScope()));
+            if (unusedDeclared.size() < before) {
+                getLog().info("maven.test.skip is set: test scoped dependencies are not analyzed for being unused");
+            }
+        }
+
         if (ignoreUnusedRuntime) {
             filterArtifactsByScope(unusedDeclared, Artifact.SCOPE_RUNTIME);
         }
@@ -383,6 +407,12 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
         boolean reported = false;
         boolean warning = false;
 
+        for (String entry : unneededForcedUsage) {
+            logDependencyWarning(ForcedUsage.message(entry));
+            reported = true;
+            warning = true;
+        }
+
         if (verbose && !usedDeclared.isEmpty()) {
             getLog().info("Used declared dependencies found:");
 
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeReport.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeReport.java
index 03ffadd8..dfa6bfd4 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeReport.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeReport.java
@@ -108,7 +108,11 @@ public class AnalyzeReport extends AbstractMavenReport {
             analysis = analyzer.analyze(project, excludedClasses);
 
             if (usedDependencies != null) {
-                analysis = analysis.forceDeclaredDependenciesUsage(usedDependencies);
+                ForcedUsage forced = new ForcedUsage(analysis, usedDependencies);
+                forced.getUnneeded().forEach(entry -> getLog().warn(ForcedUsage.message(entry)));
+                if (forced.getToForce().length > 0) {
+                    analysis = analysis.forceDeclaredDependenciesUsage(forced.getToForce());
+                }
             }
         } catch (ProjectDependencyAnalyzerException exception) {
             throw new MavenReportException("Cannot analyze dependencies", exception);
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeReportOnly.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeReportOnly.java
new file mode 100644
index 00000000..4757abdc
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeReportOnly.java
@@ -0,0 +1,47 @@
+/*
+ * 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.dependency.analyze;
+
+import javax.inject.Inject;
+
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzer;
+import org.codehaus.plexus.i18n.I18N;
+
+/**
+ * Analyzes the dependencies of this project and produces the same report as the <code>dependency:analyze-report</code>
+ * goal. Unlike that goal, it does not fork the <code>test-compile</code> phase, so it assumes that the project was
+ * already compiled, for example by an earlier phase of the same build.
+ *
+ * @see AnalyzeReport
+ * @since 3.12.0
+ */
+@Mojo(name = "analyze-report-only", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true)
+@Execute(phase = LifecyclePhase.NONE)
+public class AnalyzeReportOnly extends AnalyzeReport {
+    // subclassed to provide annotations, without the forked test-compile of analyze-report
+
+    @Inject
+    public AnalyzeReportOnly(ProjectDependencyAnalyzer analyzer, I18N i18n) {
+        super(analyzer, i18n);
+    }
+}
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/ForcedUsage.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/ForcedUsage.java
new file mode 100644
index 00000000..216b3647
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/ForcedUsage.java
@@ -0,0 +1,74 @@
+/*
+ * 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.dependency.analyze;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis;
+
+/**
+ * Splits the <code>usedDependencies</code> entries into those the analysis already reports as used and declared, which
+ * {@link ProjectDependencyAnalysis#forceDeclaredDependenciesUsage(String[])} rejects with an exception, and the rest.
+ */
+final class ForcedUsage {
+
+    private final List<String> unneeded = new ArrayList<>();
+
+    private final List<String> toForce = new ArrayList<>();
+
+    ForcedUsage(ProjectDependencyAnalysis analysis, String[] usedDependencies) {
+        Set<String> usedDeclared = new HashSet<>();
+        for (Artifact artifact : analysis.getUsedDeclaredArtifacts()) {
+            usedDeclared.add(key(artifact));
+        }
+        // the analyzer first matches an entry against the unused declared artifacts, so such an entry is needed
+        for (Artifact artifact : analysis.getUnusedDeclaredArtifacts()) {
+            usedDeclared.remove(key(artifact));
+        }
+        for (String entry : usedDependencies) {
+            (usedDeclared.contains(entry) ? unneeded : toForce).add(entry);
+        }
+    }
+
+    /**
+     * @return the entries that are already detected as used
+     */
+    List<String> getUnneeded() {
+        return unneeded;
+    }
+
+    /**
+     * @return the entries that must still be passed to the analyzer
+     */
+    String[] getToForce() {
+        return toForce.toArray(new String[0]);
+    }
+
+    static String message(String entry) {
+        return "Unneeded forced usage of " + entry + ": the dependency is already detected as used";
+    }
+
+    private static String key(Artifact artifact) {
+        return artifact.getGroupId() + ":" + artifact.getArtifactId();
+    }
+}
diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md
index 88b783f1..1efd1fb0 100644
--- a/src/site/markdown/index.md
+++ b/src/site/markdown/index.md
@@ -38,6 +38,7 @@ The Dependency plugin has several goals:
 - [dependency:analyze-exclusions](./analyze-exclusions-mojo.html) analyzes the exclusions on dependencies and checks if the artifact actually brings in the given dependency.
 - [dependency:analyze-only](./analyze-only-mojo.html) is the same as analyze, but is meant to be bound in a pom. It does not fork the build and execute test-compile.
 - [dependency:analyze-report](./analyze-report-mojo.html) analyzes the dependencies of this project and produces a report that summarises which are: used and declared; used and undeclared; unused and declared.
+- [dependency:analyze-report-only](./analyze-report-only-mojo.html) is the same as analyze-report, but does not fork the build and execute test-compile.
 - [dependency:analyze-duplicate](./analyze-duplicate-mojo.html) analyzes the `<dependencies/>` and `<dependencyManagement/>` tags in the pom.xml and determines the duplicate declared dependencies.
 - [dependency:build-classpath](./build-classpath-mojo.html) tells Maven to output the path of the dependencies from the local repository in a classpath format to be used in java -cp. The classpath file may also be attached and installed/deployed along with the main artifact.
 - [dependency:collect](./collect-mojo.html) collects the project dependencies from the repository. It lists the groupId:artifactId:version information by downloading the pom files without downloading the actual artifacts such as jar files.
diff --git a/src/site/markdown/usage.md.vm b/src/site/markdown/usage.md.vm
index 662862c5..693b90f7 100644
--- a/src/site/markdown/usage.md.vm
+++ b/src/site/markdown/usage.md.vm
@@ -490,6 +490,12 @@ This goal is used to include a report of the dependencies in the output of the `
  </reporting>
 ```
 
+Use `analyze-report-only` instead of `analyze-report` to render the same report without forking the `test-compile` phase, for example in a build that has already compiled the project:
+
+```xml
+            <report>analyze-report-only</report>
+```
+
 `dependency:tree`
 -----------------
 
diff --git a/src/test/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojoTest.java b/src/test/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojoTest.java
index 556d58b4..83008246 100644
--- a/src/test/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojoTest.java
+++ b/src/test/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojoTest.java
@@ -29,6 +29,7 @@ import java.util.stream.Collectors;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.DefaultArtifact;
 import org.apache.maven.artifact.handler.DefaultArtifactHandler;
+import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis;
@@ -40,9 +41,11 @@ import org.junit.jupiter.api.io.TempDir;
 import org.mockito.ArgumentCaptor;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -55,6 +58,8 @@ class AbstractAnalyzeMojoTest {
 
     private final Artifact commonsIo = artifact("commons-io", "commons-io", Artifact.SCOPE_COMPILE);
 
+    private ProjectDependencyAnalyzer analyzer;
+
     private Log log;
 
     private AnalyzeOnlyMojo mojo;
@@ -81,7 +86,7 @@ class AbstractAnalyzeMojoTest {
      */
     @BeforeEach
     void setUp() throws Exception {
-        ProjectDependencyAnalyzer analyzer = mock(ProjectDependencyAnalyzer.class);
+        analyzer = mock(ProjectDependencyAnalyzer.class);
         when(analyzer.analyze(any(MavenProject.class), any()))
                 .thenReturn(new ProjectDependencyAnalysis(
                         Collections.emptySet(), setOf(jodaTime, commonsIo), Collections.emptySet(), setOf(jodaTime)));
@@ -126,4 +131,89 @@ class AbstractAnalyzeMojoTest {
 
         assertThat(warnings()).doesNotContain("Non-test scoped test only dependencies found:");
     }
+
+    private void analysisIs(ProjectDependencyAnalysis analysis) throws Exception {
+        when(analyzer.analyze(any(MavenProject.class), any())).thenReturn(analysis);
+    }
+
+    @Test
+    void testSkipDropsTestScopedUnusedDeclared() throws Exception {
+        Artifact junit = artifact("junit", "junit", Artifact.SCOPE_TEST);
+        Artifact provided = artifact("javax.servlet", "servlet-api", Artifact.SCOPE_PROVIDED);
+        analysisIs(new ProjectDependencyAnalysis(
+                Collections.emptySet(), Collections.emptySet(), setOf(junit, provided), Collections.emptySet()));
+        set(mojo, "testSkip", true);
+
+        mojo.execute();
+
+        assertThat(warnings()).contains("Unused declared dependencies found:", "   " + provided);
+        assertThat(warnings()).doesNotContain("   " + junit);
+        ArgumentCaptor<CharSequence> info = ArgumentCaptor.forClass(CharSequence.class);
+        verify(log, atLeast(1)).info(info.capture());
+        assertThat(info.getAllValues())
+                .filteredOn(m -> m.toString().contains("maven.test.skip"))
+                .hasSize(1);
+    }
+
+    @Test
+    void testScopedUnusedDeclaredIsReportedWithoutTestSkip() throws Exception {
+        Artifact junit = artifact("junit", "junit", Artifact.SCOPE_TEST);
+        analysisIs(new ProjectDependencyAnalysis(
+                Collections.emptySet(), Collections.emptySet(), setOf(junit), Collections.emptySet()));
+
+        mojo.execute();
+
+        assertThat(warnings()).contains("   " + junit);
+    }
+
+    @Test
+    void unneededForcedUsageIsAWarningNotAFailure() throws Exception {
+        Artifact logback = artifact("ch.qos.logback", "logback-classic", Artifact.SCOPE_TEST);
+        analysisIs(new ProjectDependencyAnalysis(
+                setOf(logback), Collections.emptySet(), Collections.emptySet(), Collections.emptySet()));
+        set(mojo, "usedDependencies", new String[] {"ch.qos.logback:logback-classic"});
+
+        mojo.execute();
+
+        assertThat(warnings())
+                .anyMatch(m -> m.contains("ch.qos.logback:logback-classic") && m.contains("already detected as used"));
+    }
+
+    @Test
+    void unneededForcedUsageFailsTheBuildWithFailOnWarning() throws Exception {
+        Artifact logback = artifact("ch.qos.logback", "logback-classic", Artifact.SCOPE_TEST);
+        analysisIs(new ProjectDependencyAnalysis(
+                setOf(logback), Collections.emptySet(), Collections.emptySet(), Collections.emptySet()));
+        set(mojo, "usedDependencies", new String[] {"ch.qos.logback:logback-classic"});
+        set(mojo, "failOnWarning", true);
+
+        assertThatThrownBy(mojo::execute)
+                .isInstanceOf(MojoExecutionException.class)
+                .hasMessage("Dependency problems found");
+        verify(log, atLeast(1)).error(any(CharSequence.class));
+    }
+
+    @Test
+    void neededForcedUsageIsStillApplied() throws Exception {
+        Artifact logback = artifact("ch.qos.logback", "logback-classic", Artifact.SCOPE_TEST);
+        analysisIs(new ProjectDependencyAnalysis(
+                Collections.emptySet(), Collections.emptySet(), setOf(logback), Collections.emptySet()));
+        set(mojo, "usedDependencies", new String[] {"ch.qos.logback:logback-classic"});
+        set(mojo, "failOnWarning", true);
+
+        mojo.execute();
+
+        verify(log, never()).error(any(CharSequence.class));
+    }
+
+    @Test
+    void forcingAnUndeclaredDependencyStillFails() throws Exception {
+        analysisIs(new ProjectDependencyAnalysis(
+                Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet()));
+        set(mojo, "usedDependencies", new String[] {"not.declared:anywhere"});
+
+        assertThatThrownBy(mojo::execute)
+                .isInstanceOf(MojoExecutionException.class)
+                .hasMessage("Cannot analyze dependencies");
+    }
 }