Skip to content

Commit 36b3640

Browse files
authored
Skip private method stubbing in PowerMockitoDoStubbingToMockito (#957)
PowerMock's string-based `when(instance, "methodName")` API supports stubbing private methods, but standard Mockito cannot. The recipe was incorrectly rewriting these to `when(instance).methodName()`, producing uncompilable code. Now detects private methods and leaves the call unchanged with a comment guiding the user to refactor.
1 parent f044f96 commit 36b3640

2 files changed

Lines changed: 59 additions & 4 deletions

File tree

src/main/java/org/openrewrite/java/testing/mockito/PowerMockitoDoStubbingToMockito.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@
2525
import org.openrewrite.java.JavaIsoVisitor;
2626
import org.openrewrite.java.MethodMatcher;
2727
import org.openrewrite.java.search.UsesMethod;
28-
import org.openrewrite.java.tree.Expression;
29-
import org.openrewrite.java.tree.J;
30-
import org.openrewrite.java.tree.JavaType;
31-
import org.openrewrite.java.tree.Space;
28+
import org.openrewrite.java.tree.*;
29+
import org.openrewrite.marker.Markers;
30+
3231
import java.util.List;
3332

3433
import static java.util.Collections.emptyList;
3534
import static java.util.Collections.singletonList;
35+
import static org.openrewrite.java.tree.Flag.Private;
3636

3737
public class PowerMockitoDoStubbingToMockito extends Recipe {
3838

@@ -80,6 +80,19 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu
8080
String targetMethodName = (String) ((J.Literal) args.get(1)).getValue();
8181
List<Expression> extraArgs = args.subList(2, args.size());
8282

83+
// Private methods cannot be stubbed with standard Mockito; leave unchanged and add a comment
84+
JavaType.Method targetMethod = resolveTargetMethod(
85+
firstArg.getType(), targetMethodName, extraArgs.size());
86+
if (targetMethod != null && targetMethod.getFlags().contains(Private)) {
87+
String comment = " PowerMock private method stubbing is not supported by Mockito. Refactor the private method to package-private or extract to a collaborator.";
88+
if (mi.getPrefix().getComments().stream().noneMatch(c -> c.printComment(getCursor()).endsWith(comment.trim()))) {
89+
return mi.withPrefix(mi.getPrefix().withComments(ListUtils.concat(
90+
mi.getPrefix().getComments(),
91+
new TextComment(false, comment, "\n" + mi.getPrefix().getIndent(), Markers.EMPTY))));
92+
}
93+
return mi;
94+
}
95+
8396
// Rewrite: doX().when(instance, "method", args...) → doX().when(instance).method(args...)
8497

8598
// 1. Create when(instance) - strip method name and extra args, keep just the instance

src/test/java/org/openrewrite/java/testing/mockito/PowerMockitoDoStubbingToMockitoTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,48 @@ void test() throws Exception {
147147
);
148148
}
149149

150+
@Test
151+
void addsCommentForPrivateMethodStubbing() {
152+
//language=java
153+
rewriteRun(
154+
java(
155+
"""
156+
import org.junit.jupiter.api.BeforeEach;
157+
import org.powermock.api.mockito.PowerMockito;
158+
import java.util.Calendar;
159+
160+
class MyTest {
161+
162+
private Calendar calendarSpy;
163+
164+
@BeforeEach
165+
void setUp() throws Exception {
166+
calendarSpy = PowerMockito.spy(Calendar.getInstance());
167+
PowerMockito.doNothing().when(calendarSpy, "updateTime");
168+
}
169+
}
170+
""",
171+
"""
172+
import org.junit.jupiter.api.BeforeEach;
173+
import org.powermock.api.mockito.PowerMockito;
174+
import java.util.Calendar;
175+
176+
class MyTest {
177+
178+
private Calendar calendarSpy;
179+
180+
@BeforeEach
181+
void setUp() throws Exception {
182+
calendarSpy = PowerMockito.spy(Calendar.getInstance());
183+
// PowerMock private method stubbing is not supported by Mockito. Refactor the private method to package-private or extract to a collaborator.
184+
PowerMockito.doNothing().when(calendarSpy, "updateTime");
185+
}
186+
}
187+
"""
188+
)
189+
);
190+
}
191+
150192
@Test
151193
void doStubbingWithStringMethodNameAndArgs() {
152194
//language=java

0 commit comments

Comments
 (0)