Skip to content

Commit 86f2308

Browse files
fix: retain doNothing() stubs inside lambda bodies to prevent uncompilable code (#1009)
* fix: retain doNothing() stubs inside lambda bodies to prevent uncompilable empty lambda body * fix: retain doNothing() stubs in expression lambda and switch expression arms to prevent uncompilable code * Update src/main/java/org/openrewrite/java/testing/mockito/RemoveDoNothingForDefaultMocks.java Co-authored-by: Tim te Beek <timtebeek@gmail.com> * Inline parent-cursor checks and drop redundant null guard Folds isExpressionLambdaBody()/isSwitchExpressionArm() into the single call site and removes the unnecessary mi != null check. --------- Co-authored-by: Tim te Beek <tim@moderne.io> Co-authored-by: Tim te Beek <timtebeek@gmail.com>
1 parent 45d2528 commit 86f2308

2 files changed

Lines changed: 300 additions & 1 deletion

File tree

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex
7373
@Override
7474
public J.@Nullable MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
7575
J.MethodInvocation mi = super.visitMethodInvocation(method, ctx);
76-
if (mi != null && isDoNothingOnMockField(mi)) {
76+
if (isDoNothingOnMockField(mi)) {
77+
// Retain because if removed would leave a dangling -> producing uncompilable code
78+
Object value = getCursor().getParentTreeCursor().getValue();
79+
if (value instanceof J.Lambda || value instanceof J.Case && ((J.Case) value).getStatements().isEmpty()) {
80+
return mi;
81+
}
7782
maybeRemoveImport("org.mockito.Mockito.doNothing");
7883
return null;
7984
}

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

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,300 @@ interface Client {
338338
);
339339
}
340340

341+
@Test
342+
void retainsDoNothingInSwitchExpressionArm() {
343+
rewriteRun(
344+
//language=Java
345+
java(
346+
"""
347+
import org.junit.Test;
348+
import org.junit.runner.RunWith;
349+
import org.mockito.Mock;
350+
import org.mockito.junit.MockitoJUnitRunner;
351+
import java.io.BufferedWriter;
352+
import java.io.IOException;
353+
354+
import static org.mockito.Mockito.doNothing;
355+
356+
@RunWith(MockitoJUnitRunner.class)
357+
class MyTest {
358+
@Mock
359+
private BufferedWriter bufferedWriter;
360+
361+
@Test
362+
public void test() throws IOException {
363+
String status = System.getProperty("status", "ACTIVE");
364+
switch (status) {
365+
case "ACTIVE" -> doNothing().when(bufferedWriter).write("active");
366+
default -> {}
367+
}
368+
}
369+
}
370+
"""
371+
)
372+
);
373+
}
374+
375+
@Test
376+
void removesDoNothingInSwitchExpressionArmBlockLeavingEmptyBlock() {
377+
rewriteRun(
378+
//language=Java
379+
java(
380+
"""
381+
import org.junit.Test;
382+
import org.junit.runner.RunWith;
383+
import org.mockito.Mock;
384+
import org.mockito.junit.MockitoJUnitRunner;
385+
import java.io.BufferedWriter;
386+
import java.io.IOException;
387+
388+
import static org.mockito.Mockito.doNothing;
389+
390+
@RunWith(MockitoJUnitRunner.class)
391+
class MyTest {
392+
@Mock
393+
private BufferedWriter bufferedWriter;
394+
395+
@Test
396+
public void test() throws IOException {
397+
String status = System.getProperty("status", "ACTIVE");
398+
switch (status) {
399+
case "ACTIVE" -> {
400+
doNothing().when(bufferedWriter).write("active");
401+
}
402+
default -> {}
403+
}
404+
}
405+
}
406+
""",
407+
"""
408+
import org.junit.Test;
409+
import org.junit.runner.RunWith;
410+
import org.mockito.Mock;
411+
import org.mockito.junit.MockitoJUnitRunner;
412+
import java.io.BufferedWriter;
413+
import java.io.IOException;
414+
415+
@RunWith(MockitoJUnitRunner.class)
416+
class MyTest {
417+
@Mock
418+
private BufferedWriter bufferedWriter;
419+
420+
@Test
421+
public void test() throws IOException {
422+
String status = System.getProperty("status", "ACTIVE");
423+
switch (status) {
424+
case "ACTIVE" -> {
425+
}
426+
default -> {}
427+
}
428+
}
429+
}
430+
"""
431+
)
432+
);
433+
}
434+
435+
@Test
436+
void removesDoNothingWhenNotSoleStatementInSwitchExpressionArmBlock() {
437+
rewriteRun(
438+
//language=Java
439+
java(
440+
"""
441+
import org.junit.Test;
442+
import org.junit.runner.RunWith;
443+
import org.mockito.Mock;
444+
import org.mockito.junit.MockitoJUnitRunner;
445+
import java.io.BufferedWriter;
446+
import java.io.IOException;
447+
448+
import static org.mockito.Mockito.doNothing;
449+
450+
@RunWith(MockitoJUnitRunner.class)
451+
class MyTest {
452+
@Mock
453+
private BufferedWriter bufferedWriter;
454+
455+
@Test
456+
public void test() throws IOException {
457+
String status = System.getProperty("status", "ACTIVE");
458+
switch (status) {
459+
case "ACTIVE" -> {
460+
doNothing().when(bufferedWriter).write("active");
461+
System.out.println("other statement");
462+
}
463+
default -> {}
464+
}
465+
}
466+
}
467+
""",
468+
"""
469+
import org.junit.Test;
470+
import org.junit.runner.RunWith;
471+
import org.mockito.Mock;
472+
import org.mockito.junit.MockitoJUnitRunner;
473+
import java.io.BufferedWriter;
474+
import java.io.IOException;
475+
476+
@RunWith(MockitoJUnitRunner.class)
477+
class MyTest {
478+
@Mock
479+
private BufferedWriter bufferedWriter;
480+
481+
@Test
482+
public void test() throws IOException {
483+
String status = System.getProperty("status", "ACTIVE");
484+
switch (status) {
485+
case "ACTIVE" -> {
486+
System.out.println("other statement");
487+
}
488+
default -> {}
489+
}
490+
}
491+
}
492+
"""
493+
)
494+
);
495+
}
496+
497+
@Test
498+
void retainsDoNothingInsideLambdaBody() {
499+
rewriteRun(
500+
//language=Java
501+
java(
502+
"""
503+
import org.junit.Test;
504+
import org.junit.runner.RunWith;
505+
import org.mockito.Mock;
506+
import org.mockito.junit.MockitoJUnitRunner;
507+
import java.io.BufferedWriter;
508+
import java.io.IOException;
509+
import java.util.List;
510+
511+
import static org.mockito.Mockito.doNothing;
512+
513+
@RunWith(MockitoJUnitRunner.class)
514+
class MyTest {
515+
@Mock
516+
private BufferedWriter bufferedWriter;
517+
518+
@Test
519+
public void test() throws IOException {
520+
List<String> texts = List.of("first", "second");
521+
texts.forEach(text -> doNothing().when(bufferedWriter).write(text));
522+
}
523+
}
524+
"""
525+
)
526+
);
527+
}
528+
529+
@Test
530+
void removesDoNothingInLambdaBlockLeavingEmptyBlock() {
531+
rewriteRun(
532+
//language=Java
533+
java(
534+
"""
535+
import org.junit.Test;
536+
import org.junit.runner.RunWith;
537+
import org.mockito.Mock;
538+
import org.mockito.junit.MockitoJUnitRunner;
539+
import java.io.BufferedWriter;
540+
import java.io.IOException;
541+
542+
import static org.mockito.Mockito.doNothing;
543+
544+
@RunWith(MockitoJUnitRunner.class)
545+
class MyTest {
546+
@Mock
547+
private BufferedWriter bufferedWriter;
548+
549+
@Test
550+
public void test() throws IOException {
551+
Runnable r = () -> {
552+
doNothing().when(bufferedWriter).write("test");
553+
};
554+
}
555+
}
556+
""",
557+
"""
558+
import org.junit.Test;
559+
import org.junit.runner.RunWith;
560+
import org.mockito.Mock;
561+
import org.mockito.junit.MockitoJUnitRunner;
562+
import java.io.BufferedWriter;
563+
import java.io.IOException;
564+
565+
@RunWith(MockitoJUnitRunner.class)
566+
class MyTest {
567+
@Mock
568+
private BufferedWriter bufferedWriter;
569+
570+
@Test
571+
public void test() throws IOException {
572+
Runnable r = () -> {
573+
};
574+
}
575+
}
576+
"""
577+
)
578+
);
579+
}
580+
581+
@Test
582+
void removesDoNothingWhenNotSoleStatementInLambdaBlock() {
583+
rewriteRun(
584+
//language=Java
585+
java(
586+
"""
587+
import org.junit.Test;
588+
import org.junit.runner.RunWith;
589+
import org.mockito.Mock;
590+
import org.mockito.junit.MockitoJUnitRunner;
591+
import java.io.BufferedWriter;
592+
import java.io.IOException;
593+
594+
import static org.mockito.Mockito.doNothing;
595+
596+
@RunWith(MockitoJUnitRunner.class)
597+
class MyTest {
598+
@Mock
599+
private BufferedWriter bufferedWriter;
600+
601+
@Test
602+
public void test() throws IOException {
603+
Runnable r = () -> {
604+
doNothing().when(bufferedWriter).write("test");
605+
System.out.println("other statement");
606+
};
607+
}
608+
}
609+
""",
610+
"""
611+
import org.junit.Test;
612+
import org.junit.runner.RunWith;
613+
import org.mockito.Mock;
614+
import org.mockito.junit.MockitoJUnitRunner;
615+
import java.io.BufferedWriter;
616+
import java.io.IOException;
617+
618+
@RunWith(MockitoJUnitRunner.class)
619+
class MyTest {
620+
@Mock
621+
private BufferedWriter bufferedWriter;
622+
623+
@Test
624+
public void test() throws IOException {
625+
Runnable r = () -> {
626+
System.out.println("other statement");
627+
};
628+
}
629+
}
630+
"""
631+
)
632+
);
633+
}
634+
341635
@Test
342636
void noChangeWithoutDoNothing() {
343637
rewriteRun(

0 commit comments

Comments
 (0)