Allow declaring mock interactions in @SelfType(Specification) traits#2377
Conversation
Add a third external-interaction mechanism: a Groovy trait annotated with `@groovy.transform.SelfType(Specification)`. The self-type guarantees that `this` is a Specification wherever the trait is mixed in, so the trait's methods may declare interactions and create mocks exactly as inside a spec, becoming reusable helpers that any spec inherits by implementing the trait. SpockTransform (a global transform) runs before Groovy's trait transform, so it sees the trait as a plain class with instance-method bodies and rewrites them against `this`. Groovy's trait transform then relocates each body into the `$Trait$Helper` and rewrites `this` to the `$self` parameter (the real spec instance at runtime). Detection is `Traits.isTrait` plus a `@SelfType` value assignable to `Specification`; the trait rewriter reuses the external SPI with `guardSpecNotNull=false` (the receiver is non-null by construction). The self-type may be a subclass of `Specification`; static trait methods cannot declare interactions (no instance to reach the spec through). Adds the trait detection and `processSpecificationTrait` in `SpockTransform`, the `SelfType` AST node, behaviour tests (cardinality, stubbing, mock creation, self-type subclass, static-method error), and an AST snapshot showing the relocated `$self`-based output.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## external-mock-interactions-2-interactions-annotation #2377 +/- ##
==========================================================================================
- Coverage 82.53% 82.51% -0.03%
- Complexity 4936 4940 +4
==========================================================================================
Files 481 481
Lines 15454 15478 +24
Branches 1990 1999 +9
==========================================================================================
+ Hits 12755 12771 +16
- Misses 1993 1998 +5
- Partials 706 709 +3
🚀 New features to boost your workflow:
|
✅ All tests passed ✅🏷️ Commit: 02937a1 Learn more about TestLens at testlens.app. |

Add a third external-interaction mechanism: a Groovy trait annotated with
@groovy.transform.SelfType(Specification). The self-type guarantees thatthisis a Specification wherever the trait is mixed in, so the trait's methodsmay declare interactions and create mocks exactly as inside a spec, becoming
reusable helpers that any spec inherits by implementing the trait.
SpockTransform (a global transform) runs before Groovy's trait transform, so it
sees the trait as a plain class with instance-method bodies and rewrites them
against
this. Groovy's trait transform then relocates each body into the$Trait$Helperand rewritesthisto the$selfparameter (the real specinstance at runtime). Detection is
Traits.isTraitplus a@SelfTypevalueassignable to
Specification; the trait rewriter reuses the external SPI withguardSpecNotNull=false(the receiver is non-null by construction). Theself-type may be a subclass of
Specification; static trait methods cannotdeclare interactions (no instance to reach the spec through).
Adds the trait detection and
processSpecificationTraitinSpockTransform, theSelfTypeAST node, behaviour tests (cardinality, stubbing, mock creation,self-type subclass, static-method error), and an AST snapshot showing the
relocated
$self-based output.