From e5287335552d8fbebaf5241ea8466b0455df2df1 Mon Sep 17 00:00:00 2001
From: Tobias Brennecke
Date: Mon, 29 Jan 2018 13:25:12 +0100
Subject: [PATCH] Fix #817 Allow specifying global extension order
---
.../runtime/GlobalExtensionRegistry.java | 23 +++++++++++++++----
.../runtime/IExtensionRegistry.java | 4 ++--
.../GlobalExtensionRegistrySpec.groovy | 21 +++++++++++++++++
3 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/spock-core/src/main/java/org/spockframework/runtime/GlobalExtensionRegistry.java b/spock-core/src/main/java/org/spockframework/runtime/GlobalExtensionRegistry.java
index 05bdffe255..3fabcddc60 100644
--- a/spock-core/src/main/java/org/spockframework/runtime/GlobalExtensionRegistry.java
+++ b/spock-core/src/main/java/org/spockframework/runtime/GlobalExtensionRegistry.java
@@ -27,17 +27,32 @@
* Maintains a registry of global Spock extensions and their configuration objects,
* which can be used to configure other extensions.
*
+ * If an extension is specified in two or more {@code IGlobalExtension} files on the classpath, it will only
+ * be processed for the first time it is discovered.
+ * This allows processing other extensions (e.g. Spring) before custom ones by listing the order of extensions
+ * explicitly in the file.
+ *
+ *
+ * For instance this will load and run {@code SpringExtension} before {@code MyExtension}:
+ *
{@code
+ * org.spockframework.spring.SpringExtension
+ * com.example.MyExtension}
+ *
+ *
+ *
* @author Peter Niederwieser
*/
public class GlobalExtensionRegistry implements IExtensionRegistry, IConfigurationRegistry {
- private final List> globalExtensionClasses;
+ private final Set> globalExtensionClasses;
private final Map, Object> configurationsByType = new HashMap<>();
private final Map configurationsByName = new HashMap<>();
- private final List globalExtensions = new ArrayList<>();
+ private final Set globalExtensions = new LinkedHashSet<>();
GlobalExtensionRegistry(List> globalExtensionClasses, List> initialConfigurations) {
- this.globalExtensionClasses = globalExtensionClasses;
+ // Only add an extension the first time it is encountered, i.e
+ // turns [A, A, B, A,] into [A,B]
+ this.globalExtensionClasses = new LinkedHashSet<>(globalExtensionClasses);
initializeConfigurations(initialConfigurations);
}
@@ -72,7 +87,7 @@ public Object getConfigurationByName(String name) {
}
@Override
- public List getGlobalExtensions() {
+ public Set getGlobalExtensions() {
return globalExtensions;
}
diff --git a/spock-core/src/main/java/org/spockframework/runtime/IExtensionRegistry.java b/spock-core/src/main/java/org/spockframework/runtime/IExtensionRegistry.java
index 61b632b896..bee39f8cc6 100644
--- a/spock-core/src/main/java/org/spockframework/runtime/IExtensionRegistry.java
+++ b/spock-core/src/main/java/org/spockframework/runtime/IExtensionRegistry.java
@@ -16,8 +16,8 @@
import org.spockframework.runtime.extension.IGlobalExtension;
-import java.util.List;
+import java.util.Set;
public interface IExtensionRegistry {
- List getGlobalExtensions();
+ Set getGlobalExtensions();
}
diff --git a/spock-specs/src/test/groovy/org/spockframework/runtime/GlobalExtensionRegistrySpec.groovy b/spock-specs/src/test/groovy/org/spockframework/runtime/GlobalExtensionRegistrySpec.groovy
index 58b55f5dc0..3f98a2f51e 100644
--- a/spock-specs/src/test/groovy/org/spockframework/runtime/GlobalExtensionRegistrySpec.groovy
+++ b/spock-specs/src/test/groovy/org/spockframework/runtime/GlobalExtensionRegistrySpec.groovy
@@ -161,6 +161,27 @@ class GlobalExtensionRegistrySpec extends Specification {
e.message.contains("unknown configuration class")
}
+ // See https://github.com/spockframework/spock/issues/817
+ def "Extensions discovered later in the classpath are ignored if already processed earlier"() {
+ when:
+ def registry = new GlobalExtensionRegistry(extensionClasses, [])
+ registry.initializeGlobalExtensions()
+
+ then:
+ registry.globalExtensions*.class == expectedExtensionClasses
+
+ where:
+ // Ignore subsequent additions, even if they appear later in the list
+ extensionClasses || expectedExtensionClasses
+ [MyExtension, MyExtension] || [MyExtension]
+ [SpringExtension, MyExtension, SpringExtension] || [SpringExtension, MyExtension]
+ [SpringExtension, SpringExtension, MyExtension, SpringExtension] || [SpringExtension, MyExtension]
+ }
+
+ static class SpringExtension extends AbstractGlobalExtension {
+
+ }
+
static class MyExtension extends AbstractGlobalExtension {
static instantiated = false