spockframework / spockframework/spock

Accessing Spring from custom extension: Change global extension execution order

Open
#817 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
3.6k
Forks
483
PR merge metrics
No merged PRs in 30d

Description

Issue description

Currently global extensions are executed in the order they are discovered in the class path. That poses a problem when writing custom extensions which try to access fields in the Specification which will be initialized by Spring via @Autowired.
When I have MyGlobalExtension in MyProject, which depends on spock-spring and last on spock-core, the Spring extension will always add its IMethodInterceptors after MyGlobalExtension.

As far as I understand, there are a few possible workarounds (solutions) to the problem:

  • Allow defining the order other extensions by listing them META-INF/services/org.spockframework.runtime.extension.IGlobalExtension, so the globalExtensionClasses in GlobalExtensionRegistry would probably become a LinkedHashSet<Class<?>>. This would make the order of extensions configurable explicitly. (BUG: Currently the SpringExtension will be loaded twice if you do add it to your own extension configuration file)
  • Reverse the order of Extensions before execution in ExtensionRunner:
  private void runGlobalExtensions() {
    final List<IGlobalExtension> globalExtensions = new ArrayList<IGlobalExtension>(extensionRegistry.getGlobalExtensions());
    Collections.reverse(globalExtensions);
    for (IGlobalExtension extension : globalExtensions) {
      extension.visitSpec(spec);
    }
  }

This ensures that all extensions in dependencies are loaded first, but would not fix the problem between extensions in different dependencies on the classpath

  • Always load the Spring extension first programatically

I will happily contribute a fix along with tests and a Gist if required :)

Java/JDK

java -version
1.7+

Groovy version

Note that versions older than 2.0 are no longer supported.

groovy -version
2.4

Build tool version

Gradle

gradle -version
Gradle wrapper from spock-example project

Operating System

Windows 10

IDE

IntelliJ

Build-tool dependencies used

Gradle/Grails
compile 'org.spockframework:spock-core:1.1-groovy-2.4'
compile 'org.spockframework:spock-spring:1.1-groovy-2.4'

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read GlobalExtensionRegistry and ExtensionRunner first, then inspect the META-INF/services/org.spockframework.runtime.extension.IGlobalExtension configuration mentioned in the issue. Identify the existing tests covering global extension loading and ordering. Done means the chosen ordering behavior is implemented, duplicate SpringExtension loading is addressed, and custom extensions can access Spring-initialized fields.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy, java
Domain
testing-qa
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.