Skip to content

Commit

Permalink
Fix docs about initializer method interceptors (spockframework#1666)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vampire authored Feb 22, 2024
1 parent a68cd31 commit 4b65efc
Show file tree
Hide file tree
Showing 3 changed files with 538 additions and 514 deletions.
19 changes: 10 additions & 9 deletions docs/extensions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -990,13 +990,13 @@ An ellipsis in the figure means that the block before it can be repeated an arbi
The `... method interceptors` are of course only run if there are actual methods of this type to be executed (the white
boxes) and those can <<Injecting Method Parameters, inject parameters>> to be given to the method that will be run.

The difference between shared initializer interceptor and shared initializer method interceptor and between initializer
interceptor and initializer method interceptor - as there can be at most one of those methods each - is, that there are
only the two methods if there are `@Shared`, respectively non-`@Shared`, fields that get values assigned at declaration
time. The compiler will put those initializations in a generated method and call it at the proper place in the
lifecycle. So if there are no such initializations, no method is generated and thus the method interceptor is never
The shared initializer method interceptor and initializer method interceptor are called around two methods that are
generated by the compiler if there are `@Shared`, respectively non-`@Shared`, fields that get values assigned at
declaration time. The compiler will put those initializations in a generated method and call it at the proper place in
the lifecycle. So if there are no such initializations, no method is generated and thus the method interceptor is never
called. The non-method interceptors are always called at the proper place in the lifecycle to do work that has to be
done at that time.
done at that time. There can also be multiple such methods, if you for example have a super specification that itself
has fields with initialization expressions.

To create an interceptor to be attached to an interception point, you need to create a class that implements the
interface `IMethodInterceptor`. This interface has the sole method `intercept(IMethodInvocation invocation)`. The
Expand All @@ -1009,9 +1009,10 @@ interception points, there is also the convenience class `AbstractMethodIntercep
provides various methods for overriding that are called for the various interception points. Most of these methods have
a double meaning, like `interceptSetupMethod` which is called for the `setup interceptor` and the `setup method
interceptor`. If you attach your interceptor to both of them and need a differentiation, you can check for
`invocation.method.reflection`, which will be set in the method interceptor case and `null` otherwise. Alternatively you
can of course build two different interceptors or add a parameter to your interceptor and create two instances, telling
each at addition time whether it is attached to the method interceptor or the other one.
`invocation.method.reflection`, which will be set in the method interceptor case and `null` otherwise, or you can check
`invocation.method.name` which behaves the same, or you can check for `invocation.target == invocation.instance`.
Alternatively, you can of course build two different interceptors or add a parameter to your interceptor and create
two instances, telling each at addition time whether it is attached to the method interceptor or the other one.

[source,groovy,indent=0]
----
Expand Down
Binary file modified docs/images/spock_interceptors.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 4b65efc

Please sign in to comment.