Skip to content

Commit

Permalink
Add a NoMissingTypes Precondition to CleanupMockitoImports (#539)
Browse files Browse the repository at this point in the history
* Add a NoMissingTypes Precondition to CleanupMockitoImports to prevent changes if types are missing

* Specifically handle Mockito Kotlin imports

---------

Co-authored-by: Tim te Beek <tim@moderne.io>
  • Loading branch information
gideon-sunbit and timtebeek committed Jun 26, 2024
1 parent 68194d3 commit fd0eb2d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 19 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ dependencies {
testRuntimeOnly("net.datafaker:datafaker:latest.release") {
exclude(group = "org.yaml", module = "snakeyaml")
}
testRuntimeOnly("org.mockito.kotlin:mockito-kotlin:latest.release")
testRuntimeOnly("org.testcontainers:testcontainers:latest.release")
testRuntimeOnly("org.testcontainers:nginx:latest.release")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ public String getDescription() {

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(new UsesType<>("org.mockito.*", false), new CleanupMockitoImportsVisitor());
return Preconditions.check(
new UsesType<>("org.mockito.*", false),
new CleanupMockitoImportsVisitor());
}

private static class CleanupMockitoImportsVisitor extends JavaIsoVisitor<ExecutionContext> {
Expand Down Expand Up @@ -104,12 +106,18 @@ private static class CleanupMockitoImportsVisitor extends JavaIsoVisitor<Executi

for (J.Import _import : sf.getImports()) {
if (_import.getPackageName().startsWith("org.mockito")) {
if (_import.isStatic()) {
boolean isMockitoKotlinImport = _import.getPackageName().startsWith("org.mockito.kotlin");
if (_import.isStatic() || isMockitoKotlinImport) {
String staticName = _import.getQualid().getSimpleName();
if ("*".equals(staticName) && !possibleMockitoMethod(unknownTypeMethodInvocationNames)) {
maybeRemoveImport(_import.getPackageName() + "." + _import.getClassName());
} else if (!"*".equals(staticName) && !unknownTypeMethodInvocationNames.contains(staticName)) {
maybeRemoveImport(_import.getPackageName() + "." + _import.getClassName() + "." + staticName);
String fullyQualifiedName = _import.getPackageName();
if (!isMockitoKotlinImport) {
fullyQualifiedName += "." + _import.getClassName();
}
fullyQualifiedName += "." + staticName;
maybeRemoveImport(fullyQualifiedName);
}
} else if (qualifiedMethodInvocationNames.isEmpty()) {
maybeRemoveImport(_import.getPackageName() + "." + _import.getClassName());
Expand Down Expand Up @@ -146,8 +154,8 @@ private static class QualifiedMockitoMethodTypeVisitor extends JavaIsoVisitor<Li
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, List<String> qualifiedMethods) {
J.MethodInvocation mi = super.visitMethodInvocation(method, qualifiedMethods);
if (MOCKITO_METHOD_NAMES.contains(mi.getSimpleName())
&& mi.getSelect() != null
&& TypeUtils.isAssignableTo("org.mockito.Mockito", mi.getSelect().getType())) {
&& mi.getSelect() != null
&& TypeUtils.isAssignableTo("org.mockito.Mockito", mi.getSelect().getType())) {
qualifiedMethods.add(mi.getSimpleName());
}
return mi;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
import org.openrewrite.DocumentExample;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.java.JavaParser;
import org.openrewrite.kotlin.KotlinParser;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;
import org.openrewrite.test.TypeValidation;

import static org.openrewrite.java.Assertions.java;
import static org.openrewrite.kotlin.Assertions.kotlin;

class CleanupMockitoImportsTest implements RewriteTest {

Expand All @@ -31,6 +34,7 @@ public void defaults(RecipeSpec spec) {
spec
.parser(JavaParser.fromJavaVersion()
.classpathFromResources(new InMemoryExecutionContext(), "mockito-all-1.10"))
.parser(KotlinParser.builder().classpath("mockito-core", "mockito-kotlin"))
.recipe(new CleanupMockitoImports());
}

Expand All @@ -43,12 +47,12 @@ void removesUnusedMockitoImport() {
"""
import org.mockito.Mock;
import java.util.Arrays;
public class MyTest {}
""",
"""
import java.util.Arrays;
public class MyTest {}
"""
)
Expand All @@ -65,7 +69,7 @@ void leavesOtherImportsAlone() {
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
public class MyTest {}
"""
)
Expand All @@ -85,7 +89,7 @@ void doNotRemoveImportsPossiblyAssociatedWithAnUntypedMockitoMethod() {
class MyObjectTest {
MyObject myObject;
MyMockClass myMock;
void test() {
when(myObject.getSomeField()).thenReturn("testValue");
given(myObject.getSomeField()).willReturn("testValue");
Expand Down Expand Up @@ -116,7 +120,7 @@ void doNotRemoveImportsAssociatedWithAnUntypedMockitoMethodMixed() {
class MyObjectTest {
MyObject myObject;
MyMockClass myMock;
void test() {
when(myObject.getSomeField()).thenReturn("testValue");
given(myObject.getSomeField()).willReturn("testValue");
Expand Down Expand Up @@ -148,7 +152,7 @@ void doNotRemoveImportsAssociatedWithATypedMockitoMethodMixed() {
class MyObjectTest {
MyObject myObject;
MyMockClass myMock;
void test() {
when(myObject.getSomeField()).thenReturn("testValue");
given(myObject.getSomeField()).willReturn("testValue");
Expand Down Expand Up @@ -178,7 +182,7 @@ void doNotRemoveStartImportsPossiblyAssociatedWithAnUntypedMockitoMethod() {
class MyObjectTest {
MyObject myObject;
void test() {
when(myObject.getSomeField()).thenReturn("testValue");
}
Expand Down Expand Up @@ -212,7 +216,7 @@ class MyObject {
class MyObjectTest {
@Mock
MyObject myObject;
void test() {
when(myObject.getSomeField()).thenReturn("testValue");
}
Expand All @@ -226,7 +230,7 @@ void test() {
class MyObjectTest {
@Mock
MyObject myObject;
void test() {
when(myObject.getSomeField()).thenReturn("testValue");
}
Expand All @@ -243,16 +247,16 @@ void preserveStarImports() {
java(
"""
package mockito.example;
import java.util.List;
import static org.mockito.Mockito.*;
public class MockitoArgumentMatchersTest {
static class Foo {
boolean bool(String str, int i, Object obj) { return false; }
}
public void usesMatchers() {
Foo mockFoo = mock(Foo.class);
when(mockFoo.bool(anyString(), anyInt(), any(Object.class))).thenReturn(true);
Expand All @@ -270,7 +274,7 @@ void removeUnusedStarImports() {
java(
"""
import static org.mockito.Mockito.*;
public class MockitoArgumentMatchersTest {
}
""",
Expand All @@ -281,4 +285,28 @@ public class MockitoArgumentMatchersTest {
)
);
}

@Test
void handleKotlinImportsCorrectly() {
rewriteRun(
//language=kotlin
kotlin(
"""
import org.mockito.kotlin.times
class Foo {
fun bar() {
org.mockito.Mockito.mock(Foo::class.java)
}
}
""",
"""
class Foo {
fun bar() {
org.mockito.Mockito.mock(Foo::class.java)
}
}
"""
)
);
}
}

0 comments on commit fd0eb2d

Please sign in to comment.