From 40c58617eb497fc307d8d7b261ff21277920e35e Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 25 Oct 2026 19:14:31 +0100 Subject: [PATCH 1/4] Remove `CoreMatchers` imports in the reason path of `HamcrestNotMatcherToAssertJ` The three-argument `assertThat(reason, actual, not(matcher))` path only removed the `org.hamcrest.Matchers` static imports, so code that imported `not` and the matcher from `CoreMatchers` was left with unused Hamcrest imports after the migration. The two- and three-argument paths are now one code path that only differs in the `.as(reason)` call, so both remove the same imports. --- .../hamcrest/HamcrestNotMatcherToAssertJ.java | 73 +++++-------------- .../HamcrestNotMatcherToAssertJTest.java | 30 ++++++++ 2 files changed, 49 insertions(+), 54 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJ.java b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJ.java index 79376aafe..831071212 100644 --- a/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJ.java +++ b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJ.java @@ -20,6 +20,7 @@ import lombok.NoArgsConstructor; import org.jspecify.annotations.Nullable; import org.openrewrite.*; +import org.openrewrite.internal.ListUtils; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.JavaParser; import org.openrewrite.java.JavaTemplate; @@ -33,7 +34,6 @@ import java.util.List; import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; @NoArgsConstructor @AllArgsConstructor @@ -73,36 +73,29 @@ private class MigrateToAssertJVisitor extends JavaIsoVisitor { @Override public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { J.MethodInvocation mi = super.visitMethodInvocation(method, ctx); - if (ASSERT_THAT_MATCHER.matches(mi)) { - Expression notMethodInvocation = mi.getArguments().get(mi.getArguments().size() - 1); - if (!NOT_MATCHER.matches(notMethodInvocation)) { - return mi; - } - Expression matcherArgument = ((J.MethodInvocation) notMethodInvocation).getArguments().get(0); - if (mi.getArguments().size() == 2) { - return handleTwoArgumentCase(mi, matcherArgument, ctx); - } - if (mi.getArguments().size() == 3) { - return handleThreeArgumentCase(mi, matcherArgument, ctx); - } + if (!ASSERT_THAT_MATCHER.matches(mi)) { + return mi; } - return mi; - } - - private J.MethodInvocation handleTwoArgumentCase(J.MethodInvocation mi, Expression matcherArgument, ExecutionContext ctx) { - Expression actualArgument = mi.getArguments().get(0); + List mia = mi.getArguments(); + Expression notMethodInvocation = mia.get(mia.size() - 1); + if (!NOT_MATCHER.matches(notMethodInvocation)) { + return mi; + } + Expression matcherArgument = ((J.MethodInvocation) notMethodInvocation).getArguments().get(0); if (!matchersMatcher.matches(matcherArgument) || SUB_MATCHER.matches(matcherArgument)) { return mi; } - String actual = typeToIndicator(actualArgument.getType()); - List originalArguments = ((J.MethodInvocation) matcherArgument).getArguments().stream() - .filter(a -> !(a instanceof J.Empty)) - .collect(toList()); + Expression reasonArgument = mia.size() == 3 ? mia.get(0) : null; + Expression actualArgument = mia.get(mia.size() - 2); + List originalArguments = ListUtils.filter(((J.MethodInvocation) matcherArgument).getArguments(), a -> !(a instanceof J.Empty)); String argumentsTemplate = originalArguments.stream() .map(a -> typeToIndicator(a.getType())) .collect(joining(", ")); - JavaTemplate template = JavaTemplate.builder(String.format("assertThat(%s).%s(%s)", - actual, assertion, argumentsTemplate)) + JavaTemplate template = JavaTemplate.builder(String.format("assertThat(%s)%s.%s(%s)", + typeToIndicator(actualArgument.getType()), + reasonArgument != null ? ".as(#{any(String)})" : "", + assertion, + argumentsTemplate)) .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "assertj-core-3")) .staticImports("org.assertj.core.api.Assertions.assertThat") .build(); @@ -116,37 +109,9 @@ private J.MethodInvocation handleTwoArgumentCase(J.MethodInvocation mi, Expressi List templateArguments = new ArrayList<>(); templateArguments.add(actualArgument); - templateArguments.addAll(originalArguments); - return template.apply(getCursor(), mi.getCoordinates().replace(), templateArguments.toArray()); - } - - private J.MethodInvocation handleThreeArgumentCase(J.MethodInvocation mi, Expression matcherArgument, ExecutionContext ctx) { - Expression reasonArgument = mi.getArguments().get(0); - Expression actualArgument = mi.getArguments().get(1); - if (!matchersMatcher.matches(matcherArgument) || SUB_MATCHER.matches(matcherArgument)) { - return mi; + if (reasonArgument != null) { + templateArguments.add(reasonArgument); } - String actual = typeToIndicator(actualArgument.getType()); - List originalArguments = ((J.MethodInvocation) matcherArgument).getArguments().stream() - .filter(a -> !(a instanceof J.Empty)) - .collect(toList()); - String argumentsTemplate = originalArguments.stream() - .map(a -> typeToIndicator(a.getType())) - .collect(joining(", ")); - JavaTemplate template = JavaTemplate.builder(String.format("assertThat(%s).as(#{any(String)}).%s(%s)", - actual, assertion, argumentsTemplate)) - .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "assertj-core-3")) - .staticImports("org.assertj.core.api.Assertions.assertThat") - .build(); - maybeRemoveImport("org.hamcrest.Matchers.not"); - maybeRemoveImport("org.hamcrest.Matchers." + notMatcher); - maybeRemoveImport("org.hamcrest.MatcherAssert"); - maybeRemoveImport("org.hamcrest.MatcherAssert.assertThat"); - maybeAddImport("org.assertj.core.api.Assertions", "assertThat"); - - List templateArguments = new ArrayList<>(); - templateArguments.add(actualArgument); - templateArguments.add(reasonArgument); templateArguments.addAll(originalArguments); return template.apply(getCursor(), mi.getCoordinates().replace(), templateArguments.toArray()); } diff --git a/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJTest.java b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJTest.java index 779f6b2b9..72bec7eba 100644 --- a/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJTest.java +++ b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJTest.java @@ -157,4 +157,34 @@ void test() { ) ); } + + @Test + void notMatcherWithReasonFromCoreMatchers() { + rewriteRun( + spec -> spec.recipe(new HamcrestNotMatcherToAssertJ("equalTo", "isNotEqualTo")), + //language=java + java( + """ + import static org.hamcrest.CoreMatchers.equalTo; + import static org.hamcrest.CoreMatchers.not; + import static org.hamcrest.MatcherAssert.assertThat; + + class ATest { + void test(String str1, String str2) { + assertThat("Reason", str1, not(equalTo(str2))); + } + } + """, + """ + import static org.assertj.core.api.Assertions.assertThat; + + class ATest { + void test(String str1, String str2) { + assertThat(str1).as("Reason").isNotEqualTo(str2); + } + } + """ + ) + ); + } } From de466e2ee2564da0caa8006ce68c910cf95c8e23 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 25 Oct 2026 19:16:21 +0100 Subject: [PATCH 2/4] Skip Hamcrest matchers that take nested matchers in `HamcrestMatcherToAssertJ` The `*(org.hamcrest.Matcher)` exclusion only matched single-matcher overloads, not the `Matcher...` varargs, `List` or two-matcher `hasEntry` overloads, so `assertThat(list, contains(equalTo("a"), startsWith("b")))` became `assertThat(list).containsExactly(equalTo("a"), startsWith("b"))`, which compares the elements against Hamcrest matcher objects and fails (or does not compile). `HamcrestMatcherToAssertJ` and `HamcrestNotMatcherToAssertJ` now leave the call alone when any parameter or argument of the matcher is a `Matcher`, an array of matchers or an `Iterable` of matchers. --- .../hamcrest/HamcrestMatcherToAssertJ.java | 20 ++++- .../hamcrest/HamcrestNotMatcherToAssertJ.java | 3 +- .../HamcrestMatcherToAssertJTest.java | 85 +++++++++++++++++++ .../HamcrestNotMatcherToAssertJTest.java | 26 ++++++ .../MigrateHamcrestToAssertJTest.java | 27 ++++++ 5 files changed, 157 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJ.java b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJ.java index 87c26800f..04d2a81c2 100644 --- a/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJ.java +++ b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJ.java @@ -36,7 +36,7 @@ @AllArgsConstructor public class HamcrestMatcherToAssertJ extends Recipe { private static final MethodMatcher ASSERT_THAT_MATCHER = new MethodMatcher("org.hamcrest.MatcherAssert assertThat(..)"); - private static final MethodMatcher SUB_MATCHER = new MethodMatcher("org.hamcrest.*Matchers *(org.hamcrest.Matcher)"); + private static final String HAMCREST_MATCHER = "org.hamcrest.Matcher"; private static final MethodMatcher CLOSE_TO_MATCHER = new MethodMatcher("org.hamcrest.Matchers closeTo(..)"); @Option(displayName = "Hamcrest matcher", @@ -91,7 +91,7 @@ private J.MethodInvocation replace(J.MethodInvocation mi, ExecutionContext ctx) Expression reasonArgument = mia.size() == 3 ? mia.get(0) : null; Expression actualArgument = mia.get(mia.size() - 2); Expression matcherArgument = mia.get(mia.size() - 1); - if (!matchersMatcher.matches(matcherArgument) || SUB_MATCHER.matches(matcherArgument)) { + if (!matchersMatcher.matches(matcherArgument) || takesMatcher((J.MethodInvocation) matcherArgument)) { return mi; } if (argumentType != null && !TypeUtils.isAssignableTo(argumentType, actualArgument.getType())) { @@ -194,4 +194,20 @@ private String typeToIndicator(@Nullable JavaType type) { return "#{any(java.lang.Object)}"; } } + + static boolean takesMatcher(J.MethodInvocation method) { + JavaType.Method methodType = method.getMethodType(); + return (methodType != null && methodType.getParameterTypes().stream().anyMatch(HamcrestMatcherToAssertJ::isOrHoldsMatcher)) || + method.getArguments().stream().anyMatch(arg -> isOrHoldsMatcher(arg.getType())); + } + + private static boolean isOrHoldsMatcher(@Nullable JavaType type) { + if (type instanceof JavaType.Array) { + return isOrHoldsMatcher(((JavaType.Array) type).getElemType()); + } + if (type instanceof JavaType.Parameterized && TypeUtils.isAssignableTo("java.lang.Iterable", type)) { + return ((JavaType.Parameterized) type).getTypeParameters().stream().anyMatch(param -> TypeUtils.isAssignableTo(HAMCREST_MATCHER, param)); + } + return TypeUtils.isAssignableTo(HAMCREST_MATCHER, type); + } } diff --git a/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJ.java b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJ.java index 831071212..966ab03e0 100644 --- a/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJ.java +++ b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJ.java @@ -40,7 +40,6 @@ public class HamcrestNotMatcherToAssertJ extends Recipe { private static final MethodMatcher ASSERT_THAT_MATCHER = new MethodMatcher("org.hamcrest.MatcherAssert assertThat(..)"); private static final MethodMatcher NOT_MATCHER = new MethodMatcher("org.hamcrest.*Matchers not(org.hamcrest.Matcher)"); - private static final MethodMatcher SUB_MATCHER = new MethodMatcher("org.hamcrest.*Matchers *(org.hamcrest.Matcher)"); @Option(displayName = "Hamcrest Matcher", description = "The Hamcrest `not(Matcher)` to migrate to AssertJ.", @@ -82,7 +81,7 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu return mi; } Expression matcherArgument = ((J.MethodInvocation) notMethodInvocation).getArguments().get(0); - if (!matchersMatcher.matches(matcherArgument) || SUB_MATCHER.matches(matcherArgument)) { + if (!matchersMatcher.matches(matcherArgument) || HamcrestMatcherToAssertJ.takesMatcher((J.MethodInvocation) matcherArgument)) { return mi; } Expression reasonArgument = mia.size() == 3 ? mia.get(0) : null; diff --git a/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJTest.java b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJTest.java index aa1ede3a6..180d9dfb7 100644 --- a/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJTest.java +++ b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJTest.java @@ -136,6 +136,91 @@ void test() { """ )); } + + @Test + void containsVarargsMatchers() { + rewriteRun( + spec -> spec.recipe(new HamcrestMatcherToAssertJ("contains", "containsExactly", null)), + //language=java + java( + """ + import java.util.List; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.contains; + import static org.hamcrest.Matchers.equalTo; + import static org.hamcrest.Matchers.startsWith; + + class ATest { + void test(List list) { + assertThat(list, contains(equalTo("a"), startsWith("b"))); + assertThat("reason", list, contains(equalTo("a"), startsWith("b"))); + } + } + """ + )); + } + + @Test + void containsListOfMatchers() { + rewriteRun( + spec -> spec.recipe(new HamcrestMatcherToAssertJ("contains", "containsExactly", null)), + //language=java + java( + """ + import java.util.List; + import org.hamcrest.Matcher; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.contains; + + class ATest { + void test(List list, List> matchers) { + assertThat(list, contains(matchers)); + } + } + """ + )); + } + + @Test + void arrayContainingMatchers() { + rewriteRun( + spec -> spec.recipe(new HamcrestMatcherToAssertJ("arrayContaining", "containsExactly", null)), + //language=java + java( + """ + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.arrayContaining; + import static org.hamcrest.Matchers.equalTo; + + class ATest { + void test(String[] array) { + assertThat(array, arrayContaining(equalTo("a"), equalTo("b"))); + } + } + """ + )); + } + + @Test + void hasEntryMatchers() { + rewriteRun( + spec -> spec.recipe(new HamcrestMatcherToAssertJ("hasEntry", "containsEntry", null)), + //language=java + java( + """ + import java.util.Map; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.equalTo; + import static org.hamcrest.Matchers.hasEntry; + + class ATest { + void test(Map map) { + assertThat(map, hasEntry(equalTo("a"), equalTo("b"))); + } + } + """ + )); + } } @Nested diff --git a/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJTest.java b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJTest.java index 72bec7eba..c2ebcb04b 100644 --- a/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJTest.java +++ b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestNotMatcherToAssertJTest.java @@ -187,4 +187,30 @@ void test(String str1, String str2) { ) ); } + + @Test + void doNotConvertNestedMatchers() { + rewriteRun( + spec -> spec.recipe(new HamcrestNotMatcherToAssertJ("hasItems", "doesNotContain")), + //language=java + java( + """ + import java.util.List; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.equalTo; + import static org.hamcrest.Matchers.hasItems; + import static org.hamcrest.Matchers.not; + import static org.hamcrest.Matchers.startsWith; + + class ATest { + void test(List list) { + assertThat(list, not(hasItems(equalTo("a"), startsWith("b")))); + assertThat("Reason", list, not(hasItems(equalTo("a"), startsWith("b")))); + } + } + """ + ) + ); + } } diff --git a/src/test/java/org/openrewrite/java/testing/hamcrest/MigrateHamcrestToAssertJTest.java b/src/test/java/org/openrewrite/java/testing/hamcrest/MigrateHamcrestToAssertJTest.java index dc5eef067..c96f20448 100644 --- a/src/test/java/org/openrewrite/java/testing/hamcrest/MigrateHamcrestToAssertJTest.java +++ b/src/test/java/org/openrewrite/java/testing/hamcrest/MigrateHamcrestToAssertJTest.java @@ -929,5 +929,32 @@ void bar(%1$s type) { ) ); } + + @Test + void nestedMatchersAreNotPassedToAssertJ() { + //language=java + rewriteRun( + java( + """ + import java.util.List; + import java.util.Map; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.*; + + class A { + void test(List list, String[] array, Map map) { + assertThat(list, contains(equalTo("a"), startsWith("b"))); + assertThat(list, containsInAnyOrder(equalTo("a"), startsWith("b"))); + assertThat(list, hasItems(equalTo("a"), startsWith("b"))); + assertThat(list, not(hasItems(equalTo("a"), startsWith("b")))); + assertThat(array, arrayContaining(equalTo("a"), startsWith("b"))); + assertThat(map, hasEntry(equalTo("a"), startsWith("b"))); + } + } + """ + ) + ); + } } } From 7bce07ed4a6165534fde219e42cf02babc31b53e Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 25 Oct 2026 19:18:55 +0100 Subject: [PATCH 3/4] Skip varargs arrays that do not fit the actual elements in `HamcrestMatcherToAssertJ` Hamcrest infers `T` from the array, so `assertThat(list, containsInAnyOrder(states.toArray()))` compiles for a `List`, but AssertJ's `containsExactlyInAnyOrder(String...)` does not accept an `Object[]`. The test for this case locked in the non-compiling output and hid it with `methodInvocations(false)`. The recipe now leaves the call alone when an array passed to a varargs matcher has a component type that is not assignable to the element type of the actual value, and the test covers a `String[]` that does convert. --- .../hamcrest/HamcrestMatcherToAssertJ.java | 24 ++++++++++ .../HamcrestMatcherToAssertJTest.java | 47 ++++++++++--------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJ.java b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJ.java index 04d2a81c2..a4ced82de 100644 --- a/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJ.java +++ b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJ.java @@ -97,6 +97,9 @@ private J.MethodInvocation replace(J.MethodInvocation mi, ExecutionContext ctx) if (argumentType != null && !TypeUtils.isAssignableTo(argumentType, actualArgument.getType())) { return mi; } + if (passesIncompatibleVarargsArray((J.MethodInvocation) matcherArgument, actualArgument.getType())) { + return mi; + } String actual = typeToIndicator(actualArgument.getType()); J.MethodInvocation matcherArgumentMethod = (J.MethodInvocation) matcherArgument; @@ -210,4 +213,25 @@ private static boolean isOrHoldsMatcher(@Nullable JavaType type) { } return TypeUtils.isAssignableTo(HAMCREST_MATCHER, type); } + + private static boolean passesIncompatibleVarargsArray(J.MethodInvocation matcher, @Nullable JavaType actualType) { + JavaType.Method methodType = matcher.getMethodType(); + JavaType elementType = elementType(actualType); + if (methodType == null || !methodType.hasFlags(Flag.Varargs) || elementType == null) { + return false; + } + JavaType lastArgumentType = matcher.getArguments().get(matcher.getArguments().size() - 1).getType(); + return lastArgumentType instanceof JavaType.Array && !TypeUtils.isAssignableTo(elementType, ((JavaType.Array) lastArgumentType).getElemType()); + } + + private static @Nullable JavaType elementType(@Nullable JavaType type) { + if (type instanceof JavaType.Array) { + return ((JavaType.Array) type).getElemType(); + } + if (type instanceof JavaType.Parameterized && TypeUtils.isAssignableTo("java.lang.Iterable", type)) { + List typeParameters = ((JavaType.Parameterized) type).getTypeParameters(); + return typeParameters.size() == 1 ? typeParameters.get(0) : null; + } + return null; + } } diff --git a/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJTest.java b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJTest.java index 180d9dfb7..f8e4fdffb 100644 --- a/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJTest.java +++ b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToAssertJTest.java @@ -23,7 +23,6 @@ import org.openrewrite.java.JavaParser; import org.openrewrite.test.RecipeSpec; import org.openrewrite.test.RewriteTest; -import org.openrewrite.test.TypeValidation; import static org.openrewrite.java.Assertions.java; @@ -137,6 +136,26 @@ void test() { )); } + @Test + void containsInAnyOrderWithObjectArray() { + rewriteRun( + spec -> spec.recipe(new HamcrestMatcherToAssertJ("containsInAnyOrder", "containsExactlyInAnyOrder", null)), + //language=java + java( + """ + import java.util.List; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.containsInAnyOrder; + + class ATest { + void test(List list, List states) { + assertThat(list, containsInAnyOrder(states.toArray())); + } + } + """ + )); + } + @Test void containsVarargsMatchers() { rewriteRun( @@ -468,45 +487,31 @@ void test() { ); } - @SuppressWarnings("DataFlowIssue") @Test void containsInAnyOrderWithArray() { rewriteRun( - spec -> spec.recipe(new HamcrestMatcherToAssertJ("containsInAnyOrder", "containsExactlyInAnyOrder", null)) - .afterTypeValidationOptions(TypeValidation.all().methodInvocations(false)), + spec -> spec.recipe(new HamcrestMatcherToAssertJ("containsInAnyOrder", "containsExactlyInAnyOrder", null)), //language=java java( - """ - import org.junit.jupiter.api.Test; - - import java.util.ArrayList; + """ import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; class ATest { - @Test - void test() { - List list = new ArrayList<>(); - List states = null; - assertThat(list, containsInAnyOrder(states.toArray())); + void test(List list, List states) { + assertThat(list, containsInAnyOrder(states.toArray(new String[0]))); } } """, """ - import org.junit.jupiter.api.Test; - - import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; class ATest { - @Test - void test() { - List list = new ArrayList<>(); - List states = null; - assertThat(list).containsExactlyInAnyOrder(states.toArray()); + void test(List list, List states) { + assertThat(list).containsExactlyInAnyOrder(states.toArray(new String[0])); } } """ From 7b1c129ee30d43142cd5ed6db76ff7558a5c6eda Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 25 Oct 2026 19:40:06 +0100 Subject: [PATCH 4/4] Drop unused parameter declaration from `JMockitMockUpToMockitoTest` expectation `VariableReferences` in rewrite-static-analysis now matches identifiers semantically, so the `Save.text` field no longer counts as a use of the `text` parameter. --- .../java/testing/jmockit/JMockitMockUpToMockitoTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitMockUpToMockitoTest.java b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitMockUpToMockitoTest.java index dd7da0182..1b30d8e49 100644 --- a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitMockUpToMockitoTest.java +++ b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitMockUpToMockitoTest.java @@ -373,7 +373,6 @@ public void test() { }).when(mockMockUpClass).changeMsg(); try (MockedStatic mockStaticMockUpClass = mockStatic(MockUpClass.class); MockedConstruction mockConsMockUpClass = mockConstructionWithAnswer(MockUpClass.class, delegatesTo(mockMockUpClass))) { mockStaticMockUpClass.when(() -> MockUpClass.changeText(nullable(String.class))).thenAnswer(invocation -> { - String text = invocation.getArgument(0); MockUpClass.Save.text = "mockText"; return null; });