Skip to content

Commit f0f55ab

Browse files
authored
Fix Hamcrest not() unwrap infinite loop and support CoreMatchers (#1054)
* Fix infinite loop unwrapping non-Matchers not() in Hamcrest JUnit5 recipes * Migrate CoreMatchers not()/instanceOf()/isA() in Hamcrest JUnit5 recipes
1 parent fa03dcc commit f0f55ab

5 files changed

Lines changed: 132 additions & 5 deletions

File tree

src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestInstanceOfToJUnit5.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ public class HamcrestInstanceOfToJUnit5 extends Recipe {
3838
@Getter
3939
final String description = "Migrate from Hamcrest `instanceOf` and `isA` matcher to JUnit5 `assertInstanceOf` assertion.";
4040

41-
private static final MethodMatcher INSTANCE_OF_MATCHER = new MethodMatcher("org.hamcrest.Matchers instanceOf(..)");
42-
private static final MethodMatcher IS_A_MATCHER = new MethodMatcher("org.hamcrest.Matchers isA(..)");
41+
private static final MethodMatcher INSTANCE_OF_MATCHER = new MethodMatcher("org.hamcrest.*Matchers instanceOf(..)");
42+
private static final MethodMatcher IS_A_MATCHER = new MethodMatcher("org.hamcrest.*Matchers isA(..)");
4343
private static final MethodMatcher ASSERT_THAT_MATCHER = new MethodMatcher("org.hamcrest.MatcherAssert assertThat(.., org.hamcrest.Matcher)");
4444

4545
@Override
@@ -70,7 +70,7 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation mi, Execution
7070
}
7171

7272
J.MethodInvocation matcherInvocation = (J.MethodInvocation) hamcrestMatcher;
73-
while ("not".equals(matcherInvocation.getSimpleName())) {
73+
while (RemoveNotMatcherVisitor.NOT_MATCHER.matches(matcherInvocation)) {
7474
maybeRemoveImport("org.hamcrest.Matchers.not");
7575
maybeRemoveImport("org.hamcrest.CoreMatchers.not");
7676
matcherInvocation = (J.MethodInvocation) new RemoveNotMatcherVisitor().visit(matcherInvocation, ctx);

src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToJUnit5.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu
137137
J.MethodInvocation matcherInvocation = (J.MethodInvocation) hamcrestMatcher;
138138
maybeRemoveImport("org.hamcrest.MatcherAssert.assertThat");
139139

140-
while ("not".equals(matcherInvocation.getSimpleName())) {
140+
while (RemoveNotMatcherVisitor.NOT_MATCHER.matches(matcherInvocation)) {
141141
maybeRemoveImport("org.hamcrest.Matchers.not");
142142
maybeRemoveImport("org.hamcrest.CoreMatchers.not");
143143
matcherInvocation = (J.MethodInvocation) new RemoveNotMatcherVisitor().visit(matcherInvocation, ctx);

src/main/java/org/openrewrite/java/testing/hamcrest/RemoveNotMatcherVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import java.util.Objects;
2727

2828
class RemoveNotMatcherVisitor extends JavaIsoVisitor<ExecutionContext> {
29-
static final MethodMatcher NOT_MATCHER = new MethodMatcher("org.hamcrest.Matchers not(..)");
29+
static final MethodMatcher NOT_MATCHER = new MethodMatcher("org.hamcrest.*Matchers not(..)");
3030

3131
public static boolean getLogicalContext(J.MethodInvocation mi, ExecutionContext ctx) throws InvalidParameterException {
3232
Object msg = ctx.getMessage(mi.toString());

src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestInstanceOfToJUnit5Test.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
package org.openrewrite.java.testing.hamcrest;
1717

1818
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.api.Timeout;
1920
import org.openrewrite.DocumentExample;
2021
import org.openrewrite.InMemoryExecutionContext;
2122
import org.openrewrite.java.JavaParser;
2223
import org.openrewrite.test.RecipeSpec;
2324
import org.openrewrite.test.RewriteTest;
2425

26+
import java.util.concurrent.TimeUnit;
27+
2528
import static org.openrewrite.java.Assertions.java;
2629
import static org.openrewrite.test.TypeValidation.all;
2730

@@ -81,6 +84,87 @@ void testInstance() {
8184
);
8285
}
8386

87+
@Test
88+
@Timeout(value = 30, unit = TimeUnit.SECONDS, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
89+
void notFromCoreMatchers() {
90+
//language=java
91+
rewriteRun(
92+
java(
93+
"""
94+
import org.junit.jupiter.api.Test;
95+
import java.util.List;
96+
97+
import static org.hamcrest.MatcherAssert.assertThat;
98+
import static org.hamcrest.CoreMatchers.instanceOf;
99+
import static org.hamcrest.CoreMatchers.not;
100+
101+
class ATest {
102+
private static final List<Integer> list = List.of();
103+
@Test
104+
void testInstance() {
105+
assertThat(list, not(instanceOf(Integer.class)));
106+
}
107+
}
108+
""",
109+
"""
110+
import org.junit.jupiter.api.Test;
111+
import java.util.List;
112+
113+
import static org.junit.jupiter.api.Assertions.assertFalse;
114+
115+
class ATest {
116+
private static final List<Integer> list = List.of();
117+
@Test
118+
void testInstance() {
119+
assertFalse(Integer.class.isAssignableFrom(list.getClass()));
120+
}
121+
}
122+
"""
123+
)
124+
);
125+
}
126+
127+
@Test
128+
void instanceOfAndIsAFromCoreMatchers() {
129+
//language=java
130+
rewriteRun(
131+
java(
132+
"""
133+
import org.junit.jupiter.api.Test;
134+
import java.util.List;
135+
136+
import static org.hamcrest.MatcherAssert.assertThat;
137+
import static org.hamcrest.CoreMatchers.instanceOf;
138+
import static org.hamcrest.CoreMatchers.isA;
139+
140+
class ATest {
141+
private static final List<Integer> list = List.of();
142+
@Test
143+
void testInstance() {
144+
assertThat(list, instanceOf(Iterable.class));
145+
assertThat(list, isA(Iterable.class));
146+
}
147+
}
148+
""",
149+
"""
150+
import org.junit.jupiter.api.Test;
151+
import java.util.List;
152+
153+
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
154+
155+
class ATest {
156+
private static final List<Integer> list = List.of();
157+
@Test
158+
void testInstance() {
159+
assertInstanceOf(Iterable.class, list);
160+
assertInstanceOf(Iterable.class, list);
161+
}
162+
}
163+
"""
164+
)
165+
);
166+
}
167+
84168
@Test
85169
void assertionsWithReason() {
86170
//language=java

src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToJUnit5Test.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
package org.openrewrite.java.testing.hamcrest;
1717

1818
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.api.Timeout;
1920
import org.openrewrite.DocumentExample;
2021
import org.openrewrite.InMemoryExecutionContext;
2122
import org.openrewrite.java.JavaParser;
2223
import org.openrewrite.test.RecipeSpec;
2324
import org.openrewrite.test.RewriteTest;
2425

26+
import java.util.concurrent.TimeUnit;
27+
2528
import static org.openrewrite.java.Assertions.java;
2629
import static org.openrewrite.test.TypeValidation.all;
2730

@@ -158,6 +161,46 @@ void testEquals() {
158161
);
159162
}
160163

164+
@Test
165+
@Timeout(value = 30, unit = TimeUnit.SECONDS, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
166+
void notFromCoreMatchers() {
167+
//language=java
168+
rewriteRun(
169+
spec -> spec.typeValidationOptions(all().immutableExecutionContext(false)),
170+
java(
171+
"""
172+
import org.junit.jupiter.api.Test;
173+
import static org.hamcrest.MatcherAssert.assertThat;
174+
import static org.hamcrest.CoreMatchers.equalTo;
175+
import static org.hamcrest.CoreMatchers.not;
176+
177+
class ATest {
178+
@Test
179+
void testEquals() {
180+
String str1 = "Hello world!";
181+
String str2 = "Hello world!";
182+
assertThat(str1, not(equalTo(str2)));
183+
}
184+
}
185+
""",
186+
"""
187+
import org.junit.jupiter.api.Test;
188+
189+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
190+
191+
class ATest {
192+
@Test
193+
void testEquals() {
194+
String str1 = "Hello world!";
195+
String str2 = "Hello world!";
196+
assertNotEquals(str1, str2);
197+
}
198+
}
199+
"""
200+
)
201+
);
202+
}
203+
161204
@Test
162205
void greaterThan() {
163206
//language=java

0 commit comments

Comments
 (0)