Skip to content

Skip Hamcrest matchers that take nested matchers in HamcrestMatcherToAssertJ - #1236

Merged
timtebeek merged 5 commits into
mainfrom
tim/hamcrest-assertj-skip-nested-matchers
Oct 25, 2026
Merged

timtebeek merged 5 commits into
mainfrom
tim/hamcrest-assertj-skip-nested-matchers

Conversation

@timtebeek

Copy link
Copy Markdown
Member

HamcrestMatcherToAssertJ and HamcrestNotMatcherToAssertJ excluded nested matchers with a *(org.hamcrest.Matcher) pattern, which misses the Matcher... varargs, List<Matcher> and 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 matcher objects and fails (or doesn't compile). The same happened for containsInAnyOrder, hasItems, arrayContaining, hasEntry and not(hasItems(..)). Both recipes now leave the call alone when any parameter or argument of the matcher is a Matcher, an array of them or an Iterable of them.

The existing containsInAnyOrderWithArray test locked in assertThat(list).containsExactlyInAnyOrder(states.toArray()) for a List<String>, which doesn't compile, and hid that with methodInvocations(false). The template stub is typed with raw types, so type validation can't catch this. HamcrestMatcherToAssertJ now also skips a varargs matcher whose array argument has a component type that isn't assignable to the actual's element type. The test now converts a String[] and keeps Object[] as a no-change case, without the relaxation. A separate commit merges the two- and three-argument paths of HamcrestNotMatcherToAssertJ, so the reason path now also removes CoreMatchers.not and the matcher import.

Verified with ./gradlew test --tests 'org.openrewrite.java.testing.hamcrest.*' --tests 'org.openrewrite.java.testing.assertj.*': 695 tests, 1 failure. The failure is MigrateHamcrestToAssertJTest$Dependencies.assertjGradleDependencyAddedWithTestScope, a Tooling API test that can't resolve its Gradle classpath locally (Maven Central 429), so it's an environment problem and not caused by this change. The 7 new regression tests fail without the fix.

Fixes item E3 of #1211.

…erToAssertJ`

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.
…oAssertJ`

The `*(org.hamcrest.Matcher)` exclusion only matched single-matcher overloads, not the `Matcher...` varargs, `List<Matcher>` 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.
…atcherToAssertJ`

Hamcrest infers `T` from the array, so `assertThat(list, containsInAnyOrder(states.toArray()))` compiles for a `List<String>`, 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.
…xpectation

`VariableReferences` in rewrite-static-analysis now matches identifiers semantically, so the `Save.text` field no longer counts as a use of the `text` parameter.
@timtebeek
timtebeek merged commit 7e8ac45 into main Oct 25, 2026
1 check passed
@timtebeek
timtebeek deleted the tim/hamcrest-assertj-skip-nested-matchers branch October 25, 2026 20:07
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant