Skip to content

ReplaceInitMockToOpenMock: support Kotlin via KotlinTemplate branches#1055

Merged
MBoegers merged 1 commit into
mainfrom
cri-2825
Jul 21, 2026
Merged

ReplaceInitMockToOpenMock: support Kotlin via KotlinTemplate branches#1055
MBoegers merged 1 commit into
mainfrom
cri-2825

Conversation

@MBoegers

@MBoegers MBoegers commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

ReplaceInitMockToOpenMock applied JavaTemplates unconditionally, which can only emit Java, so it crashed with "Expected a template that would generate exactly one statement to replace one statement, but generated 0" when MockitoAnnotations.initMocks(this) appeared in a Kotlin @BeforeEach function.

Each of the recipe's four template sites now branches on K.CompilationUnit and uses a KotlinTemplate for Kotlin sources:

  • private lateinit var mocks: AutoCloseable for the generated field
  • @AfterEach fun tearDown() {} without throws — Kotlin has no checked exceptions, so the addThrowsIfAbsent logic stays Java-only
  • mocks = MockitoAnnotations.openMocks(this) for the statement replacement
  • mocks.close() appended to the @AfterEach body

Two Kotlin-specific notes. KotlinTemplate does not support contextSensitive() (it throws UnsupportedOperationException), so references to the generated mocks field come back untyped from the context-free parse; they are type-attributed explicitly after each template apply, which keeps full TypeValidation on in the tests. Second, class-wide autoFormat is skipped for Kotlin sources since it reformats unrelated code across the entire class — verified against a real-world 800-line Kotlin test file, where the recipe's diff is now exactly the four intended changes.

Java behavior is unchanged. New Kotlin tests cover the base transformation and appending close() to a pre-existing @AfterEach function.

  • Fixes moderneinc/customer-requests#2825

Applying the recipe to Kotlin test sources threw
"Expected a template that would generate exactly one statement to
replace one statement, but generated 0" because Java statement
templates produce no statements on a Kotlin LST.

Branch on K.CompilationUnit at each template site:
- private lateinit var mocks: AutoCloseable instead of a Java field
- @AfterEach fun tearDown() {} without throws (no checked exceptions)
- mocks = MockitoAnnotations.openMocks(this) statement replacement
- mocks.close() appended to the @AfterEach body

KotlinTemplate does not support contextSensitive(), so references to
the mocks field parse untyped; type attribution is patched onto the
identifiers and the close() invocation after each template apply.
Class-wide autoformat is skipped for Kotlin sources since it would
reformat unrelated code across the whole class.

Fixes moderneinc/customer-requests#2825
@github-project-automation github-project-automation Bot moved this from In Progress to Ready to Review in OpenRewrite Jul 21, 2026
@MBoegers
MBoegers merged commit cdad624 into main Jul 21, 2026
1 check passed
@github-project-automation github-project-automation Bot moved this from Ready to Review to Done in OpenRewrite Jul 21, 2026
@MBoegers
MBoegers deleted the cri-2825 branch July 21, 2026 12:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants