diff --git a/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestInstanceOfToJUnit5.java b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestInstanceOfToJUnit5.java new file mode 100644 index 000000000..0fbcdb35f --- /dev/null +++ b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestInstanceOfToJUnit5.java @@ -0,0 +1,116 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.testing.hamcrest; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaParser; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.search.UsesMethod; +import org.openrewrite.java.tree.Expression; +import org.openrewrite.java.tree.J; + +import java.util.ArrayList; +import java.util.List; + +public class HamcrestInstanceOfToJUnit5 extends Recipe { + @Override + public String getDisplayName() { + return "Migrate from Hamcrest `instanceOf` matcher to JUnit 5"; + } + + @Override + public String getDescription() { + return "Migrate from Hamcrest `instanceOf` and `isA` matcher to JUnit5 `assertInstanceOf` assertion."; + } + + private static final MethodMatcher INSTANCE_OF_MATCHER = new MethodMatcher("org.hamcrest.Matchers instanceOf(..)"); + private static final MethodMatcher IS_A_MATCHER = new MethodMatcher("org.hamcrest.Matchers isA(..)"); + private static final MethodMatcher ASSERT_THAT_MATCHER = new MethodMatcher("org.hamcrest.MatcherAssert assertThat(.., org.hamcrest.Matcher)"); + + @Override + public TreeVisitor getVisitor() { + TreeVisitor preconditions = Preconditions.and( + new UsesMethod<>(ASSERT_THAT_MATCHER), + Preconditions.or( + new UsesMethod<>(INSTANCE_OF_MATCHER), + new UsesMethod<>(IS_A_MATCHER))); + return Preconditions.check(preconditions, new JavaIsoVisitor() { + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation mi, ExecutionContext ctx) { + if (ASSERT_THAT_MATCHER.matches(mi)) { + Expression reason; + Expression examinedObject; + Expression hamcrestMatcher; + + if (mi.getArguments().size() == 2) { + reason = null; + examinedObject = mi.getArguments().get(0); + hamcrestMatcher = mi.getArguments().get(1); + } else if (mi.getArguments().size() == 3) { + reason = mi.getArguments().get(0); + examinedObject = mi.getArguments().get(1); + hamcrestMatcher = mi.getArguments().get(2); + } else { + return mi; + } + + J.MethodInvocation matcherInvocation = (J.MethodInvocation) hamcrestMatcher; + while ("not".equals(matcherInvocation.getSimpleName())) { + maybeRemoveImport("org.hamcrest.Matchers.not"); + maybeRemoveImport("org.hamcrest.CoreMatchers.not"); + matcherInvocation = (J.MethodInvocation) new RemoveNotMatcherVisitor().visit(matcherInvocation, ctx); + } + + if (INSTANCE_OF_MATCHER.matches(matcherInvocation) || IS_A_MATCHER.matches(matcherInvocation)) { + boolean logicalContext = RemoveNotMatcherVisitor.getLogicalContext(matcherInvocation, ctx); + + String templateString = (logicalContext ? + "assertInstanceOf(#{any(java.lang.Class)}, #{any(java.lang.Object)}" : + "assertFalse(#{any(java.lang.Class)}.isAssignableFrom(#{any(java.lang.Object)}.getClass())") + + (reason == null ? ")" : ", #{any(java.lang.String)})"); + + JavaTemplate template = JavaTemplate.builder(templateString) + .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "junit-jupiter-api-5.9")) + .staticImports("org.junit.jupiter.api.Assertions." + (logicalContext ? "assertInstanceOf" : "assertFalse")) + .build(); + + maybeRemoveImport("org.hamcrest.MatcherAssert.assertThat"); + maybeRemoveImport("org.hamcrest.Matchers.instanceOf"); + maybeRemoveImport("org.hamcrest.CoreMatchers.instanceOf"); + maybeRemoveImport("org.hamcrest.Matchers.isA"); + maybeRemoveImport("org.hamcrest.CoreMatchers.isA"); + maybeAddImport("org.junit.jupiter.api.Assertions", logicalContext ? "assertInstanceOf" : "assertFalse"); + + List arguments = new ArrayList<>(); + arguments.add(matcherInvocation.getArguments().get(0)); + arguments.add(examinedObject); + if (reason != null) { + arguments.add(reason); + } + + return template.apply(getCursor(), mi.getCoordinates().replace(), arguments.toArray()); + } + } + return super.visitMethodInvocation(mi, ctx); + } + }); + } +} diff --git a/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToJUnit5.java b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToJUnit5.java new file mode 100644 index 000000000..fe3a9a4dc --- /dev/null +++ b/src/main/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToJUnit5.java @@ -0,0 +1,191 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.testing.hamcrest; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaParser; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.search.UsesMethod; +import org.openrewrite.java.tree.Expression; +import org.openrewrite.java.tree.J; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; + +public class HamcrestMatcherToJUnit5 extends Recipe { + + private static final MethodMatcher MATCHER_ASSERT_MATCHER = new MethodMatcher("org.hamcrest.MatcherAssert assertThat(.., org.hamcrest.Matcher)"); + + @Override + public String getDisplayName() { + return "Migrate from Hamcrest `Matcher` to JUnit 5"; + } + + @Override + public String getDescription() { + return "Migrate from Hamcrest `Matcher` to JUnit 5 assertions."; + } + + @Override + public TreeVisitor getVisitor() { + return Preconditions.check( + new UsesMethod<>(MATCHER_ASSERT_MATCHER), + new MigrationFromHamcrestVisitor()); + } + + enum Replacement { + EQUALTO("equalTo", "assertEquals", "assertNotEquals", "#{any(java.lang.Object)}, #{any(java.lang.Object)}", "examinedObjThenMatcherArgs"), + EMPTYARRAY("emptyArray", "assertEquals", "assertNotEquals", "0, #{anyArray(java.lang.Object)}.length", "examinedObjOnly"), + HASENTRY("hasEntry", "assertEquals", "assertNotEquals", "#{any(java.lang.Object)}, #{any(java.util.Map)}.get(#{any(java.lang.Object)})", "matcher1ExaminedObjMatcher0"), + HASSIZE("hasSize", "assertEquals", "assertNotEquals", "#{any(java.util.Collection)}.size(), #{any(double)}", "examinedObjThenMatcherArgs"), + HASTOSTRING("hasToString", "assertEquals", "assertNotEquals", "#{any(java.lang.Object)}.toString(), #{any(java.lang.String)}", "examinedObjThenMatcherArgs"), + CLOSETO("closeTo", "assertTrue", "assertFalse", "Math.abs(#{any(double)} - #{any(double)}) < #{any(double)}", "examinedObjThenMatcherArgs"), + CONTAINSSTRING("containsString", "assertTrue", "assertFalse", "#{any(java.lang.String)}.contains(#{any(java.lang.String)}", "examinedObjThenMatcherArgs"), + EMPTY("empty", "assertTrue", "assertFalse", "#{any(java.util.Collection)}.isEmpty()", "examinedObjOnly"), + ENDSWITH("endsWith", "assertTrue", "assertFalse", "#{any(java.lang.String)}.endsWith(#{any(java.lang.String)})", "examinedObjThenMatcherArgs"), + EQUALTOIGNORINGCASE("equalToIgnoringCase", "assertTrue", "assertFalse", "#{any(java.lang.String)}.equalsIgnoreCase(#{any(java.lang.String)})", "examinedObjThenMatcherArgs"), + GREATERTHAN("greaterThan", "assertTrue", "assertFalse", "#{any(double)} > #{any(double)}", "examinedObjThenMatcherArgs"), + GREATERTHANOREQUALTO("greaterThanOrEqualTo", "assertTrue", "assertFalse", "#{any(double)} >= #{any(double)}", "examinedObjThenMatcherArgs"), + HASKEY("hasKey", "assertTrue", "assertFalse", "#{any(java.util.Map)}.containsKey(#{any(java.lang.Object)})", "examinedObjThenMatcherArgs"), + HASVALUE("hasValue", "assertTrue", "assertFalse", "#{any(java.util.Map)}.containsValue(#{any(java.lang.Object)})", "examinedObjThenMatcherArgs"), + LESSTHAN("lessThan", "assertTrue", "assertFalse", "#{any(double)} < #{any(double)}", "examinedObjThenMatcherArgs"), + LESSTHANOREQUALTO("lessThanOrEqualTo", "assertTrue", "assertFalse", "#{any(double)} <= #{any(double)}", "examinedObjThenMatcherArgs"), + STARTSWITH("startsWith", "assertTrue", "assertFalse", "#{any(java.lang.String)}.startsWith(#{any(java.lang.String)})", "examinedObjThenMatcherArgs"), + TYPECOMPATIBLEWITH("typeCompatibleWith", "assertTrue", "assertFalse", "#{any(java.lang.Class)}.isAssignableFrom(#{any(java.lang.Class)})", "matcherArgsThenExaminedObj"), + NOTNULLVALUE("notNullValue", "assertNotNull", "assertNull", "#{any(java.lang.Object)}", "examinedObjOnly"), + NULLVALUE("nullValue", "assertNull", "assertNotNull", "#{any(java.lang.Object)}", "examinedObjOnly"), + SAMEINSTANCE("sameInstance", "assertSame", "assertNotSame", "#{any(java.lang.Object)}, #{any(java.lang.Object)}", "examinedObjThenMatcherArgs"), + THEINSTANCE("theInstance", "assertSame", "assertNotSame", "#{any(java.lang.Object)}, #{any(java.lang.Object)}", "examinedObjThenMatcherArgs"), + EMPTYITERABLE("emptyIterable", "assertFalse", "assertTrue", "#{any(java.lang.Iterable)}.iterator().hasNext()", "examinedObjOnly"); + + final String hamcrest, junitPositive, junitNegative, template; + final String argumentsMethod; + + private static final Map>> methods = new HashMap<>(); + + static { + methods.put("examinedObjThenMatcherArgs", (ex, matcher) -> { + List arguments = matcher.getArguments(); + arguments.add(0, ex); + return arguments; + }); + methods.put("matcherArgsThenExaminedObj", (ex, matcher) -> { + List arguments = matcher.getArguments(); + arguments.add(ex); + return arguments; + }); + methods.put("examinedObjOnly", (ex, matcher) -> { + List arguments = new ArrayList<>(); + arguments.add(ex); + return arguments; + }); + methods.put("matcher1ExaminedObjMatcher0", (ex, matcher) -> { + List arguments = new ArrayList<>(); + arguments.add(matcher.getArguments().get(1)); + arguments.add(ex); + arguments.add(matcher.getArguments().get(0)); + return arguments; + }); + } + + Replacement(String hamcrest, String junitPositive, String junitNegative, String template, String argumentsMethod) { + this.hamcrest = hamcrest; + this.junitPositive = junitPositive; + this.junitNegative = junitNegative; + this.template = template; + this.argumentsMethod = argumentsMethod; + } + } + + private static class MigrationFromHamcrestVisitor extends JavaIsoVisitor { + + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { + J.MethodInvocation mi = super.visitMethodInvocation(method, ctx); + + if (MATCHER_ASSERT_MATCHER.matches(mi)) { + Expression reason; + Expression examinedObject; + Expression hamcrestMatcher; + + if (mi.getArguments().size() == 2) { + reason = null; + examinedObject = mi.getArguments().get(0); + hamcrestMatcher = mi.getArguments().get(1); + } else if (mi.getArguments().size() == 3) { + reason = mi.getArguments().get(0); + examinedObject = mi.getArguments().get(1); + hamcrestMatcher = mi.getArguments().get(2); + } else { + return mi; + } + + if (hamcrestMatcher instanceof J.MethodInvocation) { + J.MethodInvocation matcherInvocation = (J.MethodInvocation) hamcrestMatcher; + maybeRemoveImport("org.hamcrest.MatcherAssert.assertThat"); + + while ("not".equals(matcherInvocation.getSimpleName())) { + maybeRemoveImport("org.hamcrest.Matchers.not"); + maybeRemoveImport("org.hamcrest.CoreMatchers.not"); + matcherInvocation = (J.MethodInvocation) new RemoveNotMatcherVisitor().visit(matcherInvocation, ctx); + } + + //we do not handle nested matchers + if (!(matcherInvocation.getArguments().get(0) instanceof J.Empty)) { + if ((matcherInvocation.getArguments().get(0).getType()).toString().startsWith("org.hamcrest")) { + return mi; + } + } + + boolean logicalContext = RemoveNotMatcherVisitor.getLogicalContext(matcherInvocation, ctx); + + Replacement replacement; + try { + replacement = Replacement.valueOf(matcherInvocation.getSimpleName().toUpperCase()); + } catch (IllegalArgumentException e) { + return mi; + } + String assertion = logicalContext ? replacement.junitPositive : replacement.junitNegative; + String templateString = assertion + "(" + replacement.template + (reason == null ? ")" : ", #{any(java.lang.String)})"); + JavaTemplate template = JavaTemplate.builder(templateString) + .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "junit-jupiter-api-5.9")) + .staticImports("org.junit.jupiter.api.Assertions." + assertion) + .build(); + + maybeRemoveImport("org.hamcrest.Matchers." + replacement.hamcrest); + maybeRemoveImport("org.hamcrest.CoreMatchers." + replacement.hamcrest); + maybeAddImport("org.junit.jupiter.api.Assertions", assertion); + + List arguments = Replacement.methods.get(replacement.argumentsMethod).apply(examinedObject, matcherInvocation); + if (reason != null) { + arguments.add(reason); + } + + return template.apply(getCursor(), method.getCoordinates().replace(), arguments.toArray()); + } + } + return mi; + } + } +} diff --git a/src/main/java/org/openrewrite/java/testing/hamcrest/RemoveNotMatcherVisitor.java b/src/main/java/org/openrewrite/java/testing/hamcrest/RemoveNotMatcherVisitor.java new file mode 100644 index 000000000..cd0413de5 --- /dev/null +++ b/src/main/java/org/openrewrite/java/testing/hamcrest/RemoveNotMatcherVisitor.java @@ -0,0 +1,77 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.testing.hamcrest; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaParser; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.tree.J; + +import java.security.InvalidParameterException; +import java.util.Objects; + +class RemoveNotMatcherVisitor extends JavaIsoVisitor { + static final MethodMatcher NOT_MATCHER = new MethodMatcher("org.hamcrest.Matchers not(..)"); + + public static boolean getLogicalContext(J.MethodInvocation mi, ExecutionContext ctx) throws InvalidParameterException { + Object msg = ctx.getMessage(mi.toString()); + if (msg == null) { + return true; + } else if (msg instanceof Boolean) { + return (Boolean) msg; + } else { + throw new InvalidParameterException(); + } + } + + @Override + @SuppressWarnings("ConstantConditions") + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation mi, ExecutionContext ctx) { + if (NOT_MATCHER.matches(mi)) { + boolean logicalContext; + if (ctx.pollMessage(mi.toString()) != null) { + logicalContext = ctx.getMessage(mi.toString()); + } else { + logicalContext = true; + } + + maybeRemoveImport("org.hamcrest.Matchers.not"); + + J.MethodInvocation result; + if (Objects.requireNonNull(mi.getArguments().get(0).getType()).toString().startsWith("org.hamcrest")) { + result = mi.getArguments().get(0).withPrefix(mi.getPrefix()); + } else { + JavaTemplate template = JavaTemplate.builder("equalTo(#{any(java.lang.Object)})") + .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "hamcrest-2.2")) + .staticImports("org.hamcrest.Matchers.equalTo") + .build(); + maybeAddImport("org.hamcrest.Matchers", "equalTo"); + result = template.apply(getCursor(), mi.getCoordinates().replace(), mi.getArguments().get(0)); + } + + ctx.putMessage(result.toString(), !logicalContext); + + return result; + } else { + if (ctx.pollMessage(mi.toString()) == null) { + ctx.putMessage(mi.toString(), true); + } + } + return super.visitMethodInvocation(mi, ctx); + } +} diff --git a/src/main/resources/META-INF/rewrite/hamcrest.yml b/src/main/resources/META-INF/rewrite/hamcrest.yml index 68748c9fa..e08946662 100644 --- a/src/main/resources/META-INF/rewrite/hamcrest.yml +++ b/src/main/resources/META-INF/rewrite/hamcrest.yml @@ -31,8 +31,53 @@ recipeList: acceptTransitive: true --- type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.java.testing.hamcrest.ConsistentHamcrestMatcherImports +displayName: Use consistent Hamcrest matcher imports +description: Use consistent imports for Hamcrest matchers, and remove wrapping `is(Matcher)` calls ahead of further changes. +tags: + - testing + - hamcrest + - assertj +recipeList: + # First change `is(..)` to `Matchers.is(..)` for consistent matching + - org.openrewrite.java.ChangeMethodTargetToStatic: + methodPattern: org.hamcrest.core.* *(..) + fullyQualifiedTargetTypeName: org.hamcrest.Matchers + - org.openrewrite.java.ChangeMethodTargetToStatic: + methodPattern: org.hamcrest.collection.* *(..) + fullyQualifiedTargetTypeName: org.hamcrest.Matchers + + # Then remove wrapping `is(Matcher)` calls such that further recipes will match + - org.openrewrite.java.testing.hamcrest.RemoveIsMatcher +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.java.testing.hamcrest.MigrateHamcrestToJUnit5 +displayName: Migrate Hamcrest assertions to JUnit Jupiter +description: Migrate Hamcrest `assertThat(..)` to JUnit Jupiter `Assertions`. +tags: + - testing + - hamcrest + - assertj +recipeList: + # First change `is(..)` to `Matchers.is(..)` for consistent matching + - org.openrewrite.java.testing.hamcrest.ConsistentHamcrestMatcherImports + # Then replace `assertThat(String, boolean)` with `assertTrue(boolean, String)` + - org.openrewrite.java.ReorderMethodArguments: + methodPattern: org.hamcrest.MatcherAssert assertThat(java.lang.String, boolean) + oldParameterNames: [reason, assertion] + newParameterNames: [assertion, reason] + - org.openrewrite.java.ChangeMethodName: + methodPattern: org.hamcrest.MatcherAssert assertThat(boolean, String) + newMethodName: assertTrue + - org.openrewrite.java.ChangeMethodTargetToStatic: + methodPattern: org.hamcrest.MatcherAssert assertTrue(boolean, String) + fullyQualifiedTargetTypeName: org.junit.jupiter.api.Assertions + - org.openrewrite.java.testing.hamcrest.HamcrestInstanceOfToJUnit5 + - org.openrewrite.java.testing.hamcrest.HamcrestMatcherToJUnit5 +--- +type: specs.openrewrite.org/v1beta/recipe name: org.openrewrite.java.testing.hamcrest.MigrateHamcrestToAssertJ -displayName: Migrate to AssertJ assertions +displayName: Migrate Hamcrest assertions to AssertJ description: Migrate Hamcrest `assertThat(..)` to AssertJ `Assertions`. tags: - testing @@ -48,15 +93,7 @@ recipeList: acceptTransitive: true # First change `is(..)` to `Matchers.is(..)` for consistent matching - - org.openrewrite.java.ChangeMethodTargetToStatic: - methodPattern: org.hamcrest.core.* *(..) - fullyQualifiedTargetTypeName: org.hamcrest.Matchers - - org.openrewrite.java.ChangeMethodTargetToStatic: - methodPattern: org.hamcrest.collection.* *(..) - fullyQualifiedTargetTypeName: org.hamcrest.Matchers - - # Then remove wrapping `is(Matcher)` calls such that further recipes will match - - org.openrewrite.java.testing.hamcrest.RemoveIsMatcher + - org.openrewrite.java.testing.hamcrest.ConsistentHamcrestMatcherImports # Then remove calls to `MatcherAssert.assertThat(String, is(Matcher))` - org.openrewrite.java.testing.hamcrest.HamcrestIsMatcherToAssertJ diff --git a/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestInstanceOfToJUnit5Test.java b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestInstanceOfToJUnit5Test.java new file mode 100644 index 000000000..a63ec98cd --- /dev/null +++ b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestInstanceOfToJUnit5Test.java @@ -0,0 +1,128 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.testing.hamcrest; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class HamcrestInstanceOfToJUnit5Test implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec + .parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "junit-jupiter-api-5.9", "hamcrest-2.2")) + .recipe(new HamcrestInstanceOfToJUnit5()); + } + + @DocumentExample + @Test + void instanceOf() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import java.util.List; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.instanceOf; + import static org.hamcrest.Matchers.isA; + import static org.hamcrest.Matchers.not; + + class ATest { + private static final List list = List.of(); + @Test + void testInstance() { + assertThat(list, instanceOf(Iterable.class)); + assertThat(list, not(instanceOf(Integer.class))); + assertThat(list, isA(Iterable.class)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + import java.util.List; + + import static org.junit.jupiter.api.Assertions.assertFalse; + import static org.junit.jupiter.api.Assertions.assertInstanceOf; + + class ATest { + private static final List list = List.of(); + @Test + void testInstance() { + assertInstanceOf(Iterable.class, list); + assertFalse(Integer.class.isAssignableFrom(list.getClass())); + assertInstanceOf(Iterable.class, list); + } + } + """ + ) + ); + } + + @Test + void assertionsWithReason() { + //language=java + rewriteRun( + java( + """ + import java.util.List; + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.instanceOf; + import static org.hamcrest.Matchers.isA; + import static org.hamcrest.Matchers.not; + + class ATest { + private static final List list = List.of(); + + @Test + void testInstance() { + assertThat("Examined object is not instance of Iterable", list, instanceOf(Iterable.class)); + assertThat("Examined object is not instance of Iterable", list, isA(Iterable.class)); + assertThat("Examined object must not be instance of Integer", list, not(instanceOf(Integer.class))); + } + } + """, + """ + import java.util.List; + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertFalse; + import static org.junit.jupiter.api.Assertions.assertInstanceOf; + + class ATest { + private static final List list = List.of(); + + @Test + void testInstance() { + assertInstanceOf(Iterable.class, list, "Examined object is not instance of Iterable"); + assertInstanceOf(Iterable.class, list, "Examined object is not instance of Iterable"); + assertFalse(Integer.class.isAssignableFrom(list.getClass()), "Examined object must not be instance of Integer"); + } + } + """ + ) + ); + } +} diff --git a/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToJUnit5Test.java b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToJUnit5Test.java new file mode 100644 index 000000000..42cd23ec9 --- /dev/null +++ b/src/test/java/org/openrewrite/java/testing/hamcrest/HamcrestMatcherToJUnit5Test.java @@ -0,0 +1,937 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.testing.hamcrest; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class HamcrestMatcherToJUnit5Test implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec + .parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "junit-jupiter-api-5.9", "hamcrest-2.2")) + .recipe(new HamcrestMatcherToJUnit5()); + } + + @Test + void equalToObject() { + //language=java + rewriteRun( + java( + """ + class Biscuit { + String name; + Biscuit(String name) { + this.name = name; + } + } + """ + ), + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.equalTo; + + class BiscuitTest { + @Test + void testEquals() { + Biscuit theBiscuit = new Biscuit("Ginger"); + Biscuit myBiscuit = new Biscuit("Ginger"); + assertThat(theBiscuit, equalTo(myBiscuit)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertEquals; + + class BiscuitTest { + @Test + void testEquals() { + Biscuit theBiscuit = new Biscuit("Ginger"); + Biscuit myBiscuit = new Biscuit("Ginger"); + assertEquals(theBiscuit, myBiscuit); + } + } + """ + ) + ); + } + + @DocumentExample + @Test + void equalToString() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.equalTo; + + class ATest { + @Test + void testEquals() { + String str1 = "Hello world!"; + String str2 = "Hello world!"; + assertThat(str1, equalTo(str2)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertEquals; + + class ATest { + @Test + void testEquals() { + String str1 = "Hello world!"; + String str2 = "Hello world!"; + assertEquals(str1, str2); + } + } + """ + ) + ); + } + + @Test + void notEqualToString() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.equalTo; + import static org.hamcrest.Matchers.not; + + class ATest { + @Test + void testEquals() { + String str1 = "Hello world!"; + String str2 = "Hello world!"; + assertThat(str1, not(equalTo(str2))); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertNotEquals; + + class ATest { + @Test + void testEquals() { + String str1 = "Hello world!"; + String str2 = "Hello world!"; + assertNotEquals(str1, str2); + } + } + """ + ) + ); + } + + @Test + void greaterThan() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.greaterThan; + + class ATest { + @Test + void testEquals() { + int intt = 7; + assertThat(10, greaterThan(intt)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testEquals() { + int intt = 7; + assertTrue(10 > intt); + } + } + """ + ) + ); + } + + @Test + void greaterThanOrEqualTo() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.greaterThanOrEqualTo; + + class ATest { + @Test + void testGreaterThanOrEqualTo() { + int intt = 7; + assertThat(10, greaterThanOrEqualTo(intt)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testGreaterThanOrEqualTo() { + int intt = 7; + assertTrue(10 >= intt); + } + } + """ + ) + ); + } + + @Test + void closeTo() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.closeTo; + + class ATest { + @Test + void testCloseTo() { + double dbl = 179.1; + assertThat(dbl, closeTo(178.2, 1.0)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testCloseTo() { + double dbl = 179.1; + assertTrue(Math.abs(dbl - 178.2) < 1.0); + } + } + """ + ) + ); + } + + @Test + void collections() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import java.util.ArrayList; + import java.util.Collection; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.empty; + import static org.hamcrest.Matchers.hasSize; + + class ATest { + private static final Collection collection = new ArrayList<>(); + @Test + void testEmpty() { + assertThat(collection, empty()); + assertThat(collection, hasSize(0)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + import java.util.ArrayList; + import java.util.Collection; + + import static org.junit.jupiter.api.Assertions.assertEquals; + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + private static final Collection collection = new ArrayList<>(); + @Test + void testEmpty() { + assertTrue(collection.isEmpty()); + assertEquals(collection.size(), 0); + } + } + """ + ) + ); + } + + @Test + void arraysAndIterables() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import java.util.Arrays; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.emptyArray; + import static org.hamcrest.Matchers.emptyIterable; + + class ATest { + private static final Integer[] ints = new Integer[]{}; + @Test + void testEmpty() { + assertThat(ints, emptyArray()); + Iterable iterable = Arrays.stream(ints).toList(); + assertThat(iterable, emptyIterable()); + } + } + """, + """ + import org.junit.jupiter.api.Test; + import java.util.Arrays; + + import static org.junit.jupiter.api.Assertions.assertEquals; + import static org.junit.jupiter.api.Assertions.assertFalse; + + class ATest { + private static final Integer[] ints = new Integer[]{}; + @Test + void testEmpty() { + assertEquals(0, ints.length); + Iterable iterable = Arrays.stream(ints).toList(); + assertFalse(iterable.iterator().hasNext()); + } + } + """ + ) + ); + } + + @Test + void lessThan() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.lessThan; + + class ATest { + @Test + void testLessThan() { + int intt = 7; + assertThat(5, lessThan(intt)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testLessThan() { + int intt = 7; + assertTrue(5 < intt); + } + } + """ + ) + ); + } + + @Test + void lessThanOrEqualTo() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.lessThanOrEqualTo; + + class ATest { + @Test + void testLessThanOrEqualTo() { + int intt = 7; + assertThat(5, lessThanOrEqualTo(intt)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testLessThanOrEqualTo() { + int intt = 7; + assertTrue(5 <= intt); + } + } + """ + ) + ); + } + + @Test + void nullValue() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.nullValue; + import static org.hamcrest.Matchers.notNullValue; + + class ATest { + @Test + void testNullValue() { + Integer integer = null; + String str = "hello world"; + assertThat(integer, nullValue()); + assertThat(str, notNullValue()); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertNotNull; + import static org.junit.jupiter.api.Assertions.assertNull; + + class ATest { + @Test + void testNullValue() { + Integer integer = null; + String str = "hello world"; + assertNull(integer); + assertNotNull(str); + } + } + """ + ) + ); + } + + @Test + void sameInstance() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.not; + import static org.hamcrest.Matchers.sameInstance; + import static org.hamcrest.Matchers.theInstance; + + class ATest { + private final String string = "Hello world."; + @Test + void testSameInstance() { + String localString = string; + String differentString = "Hello void."; + assertThat(string, sameInstance(localString)); + assertThat(string, not(theInstance(differentString))); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertNotSame; + import static org.junit.jupiter.api.Assertions.assertSame; + + class ATest { + private final String string = "Hello world."; + @Test + void testSameInstance() { + String localString = string; + String differentString = "Hello void."; + assertSame(string, localString); + assertNotSame(string, differentString); + } + } + """ + ) + ); + } + + @Test + void hasEntry() { + //language=java + rewriteRun( + java( + """ + import java.util.HashMap; + import java.util.Map; + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.hasEntry; + + class ATest { + @Test + void testHasEntry() { + Map map = new HashMap<>(); + assertThat(map, hasEntry("hello", "world")); + } + } + """, + """ + import java.util.HashMap; + import java.util.Map; + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertEquals; + + class ATest { + @Test + void testHasEntry() { + Map map = new HashMap<>(); + assertEquals("world", map.get("hello")); + } + } + """ + ) + ); + } + + @Test + void hasKey() { + //language=java + rewriteRun( + java( + """ + import java.util.HashMap; + import java.util.Map; + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.hasKey; + + class ATest { + @Test + void testHasKey() { + Map map = new HashMap<>(); + assertThat(map, hasKey("hello")); + } + } + """, + """ + import java.util.HashMap; + import java.util.Map; + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testHasKey() { + Map map = new HashMap<>(); + assertTrue(map.containsKey("hello")); + } + } + """ + ) + ); + } + + @Test + void hasValue() { + //language=java + rewriteRun( + java( + """ + import java.util.HashMap; + import java.util.Map; + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.hasValue; + + class ATest { + @Test + void testHasValue() { + Map map = new HashMap<>(); + assertThat(map, hasValue("world")); + } + } + """, + """ + import java.util.HashMap; + import java.util.Map; + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testHasValue() { + Map map = new HashMap<>(); + assertTrue(map.containsValue("world")); + } + } + """ + ) + ); + } + + @Test + void typeCompatibleWith() { + //language=java + rewriteRun( + java( + """ + import java.util.List; + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.typeCompatibleWith; + + class ATest { + @Test + void testTypeCompatibleWith() { + assertThat(List.class, typeCompatibleWith(Iterable.class)); + } + } + """, + """ + import java.util.List; + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testTypeCompatibleWith() { + assertTrue(Iterable.class.isAssignableFrom(List.class)); + } + } + """ + ) + ); + } + + @Test + void containsString() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.containsString; + + class ATest { + @Test + void testTypeCompatibleWith() { + String string = "hello world"; + String substring = "llo wor"; + assertThat(string, containsString(substring)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testTypeCompatibleWith() { + String string = "hello world"; + String substring = "llo wor"; + assertTrue(string.contains(substring)); + } + } + """ + ) + ); + } + + @Test + void endsWith() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.endsWith; + + class ATest { + @Test + void testTypeCompatibleWith() { + String string = "hello world"; + String suffix = "world"; + assertThat(string, endsWith(suffix)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testTypeCompatibleWith() { + String string = "hello world"; + String suffix = "world"; + assertTrue(string.endsWith(suffix)); + } + } + """ + ) + ); + } + + @Test + void equalToIgnoringCase() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.equalToIgnoringCase; + + class ATest { + @Test + void testTypeCompatibleWith() { + String string1 = "hELLo WoRLD"; + String string2 = "HeLlO WOrLd"; + assertThat(string1, equalToIgnoringCase(string2)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testTypeCompatibleWith() { + String string1 = "hELLo WoRLD"; + String string2 = "HeLlO WOrLd"; + assertTrue(string1.equalsIgnoreCase(string2)); + } + } + """ + ) + ); + } + + @Test + void hasToString() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.hasToString; + + class ATest { + @Test + void testTypeCompatibleWith() { + StringBuilder sb = new StringBuilder(); + sb.append("hello"); + assertThat(sb, hasToString("hello")); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertEquals; + + class ATest { + @Test + void testTypeCompatibleWith() { + StringBuilder sb = new StringBuilder(); + sb.append("hello"); + assertEquals(sb.toString(), "hello"); + } + } + """ + ) + ); + } + + @Test + void startsWith() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.startsWith; + + class ATest { + @Test + void testTypeCompatibleWith() { + String string = "hello world"; + String prefix = "hello"; + assertThat(string, startsWith(prefix)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testTypeCompatibleWith() { + String string = "hello world"; + String prefix = "hello"; + assertTrue(string.startsWith(prefix)); + } + } + """ + ) + ); + } + + @Test + void assertionsWithReason() { + //language=java + rewriteRun( + java( + """ + import java.util.List; + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.startsWith; + + class ATest { + private static final List list = List.of(); + + @Test + void testAssertionsWithReason() { + String string = "hello world"; + String prefix = "hello"; + assertThat("String does not start with given prefix.", string, startsWith(prefix)); + } + } + """, + """ + import java.util.List; + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + private static final List list = List.of(); + + @Test + void testAssertionsWithReason() { + String string = "hello world"; + String prefix = "hello"; + assertTrue(string.startsWith(prefix), "String does not start with given prefix."); + } + } + """ + ) + ); + } + + @Test + void shouldNotRewriteCaseTest() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.containsString; + + class ATest { + @Test + void testTypeCompatibleWith() { + String string = "hello world"; + String substring = "llo wor"; + assertThat(string, containsString(substring)); + assertThat("String does not contain the substring", string.contains(substring)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testTypeCompatibleWith() { + String string = "hello world"; + String substring = "llo wor"; + assertTrue(string.contains(substring)); + assertThat("String does not contain the substring", string.contains(substring)); + } + } + """ + ) + ); + } +} diff --git a/src/test/java/org/openrewrite/java/testing/hamcrest/MigrateHamcrestToJUnitTest.java b/src/test/java/org/openrewrite/java/testing/hamcrest/MigrateHamcrestToJUnitTest.java new file mode 100644 index 000000000..c4a9a49ad --- /dev/null +++ b/src/test/java/org/openrewrite/java/testing/hamcrest/MigrateHamcrestToJUnitTest.java @@ -0,0 +1,149 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.testing.hamcrest; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class MigrateHamcrestToJUnitTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec + .parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "junit-jupiter-api-5.9", "hamcrest-2.2")) + .recipeFromResource("/META-INF/rewrite/hamcrest.yml", "org.openrewrite.java.testing.hamcrest.MigrateHamcrestToJUnit5"); + } + + @DocumentExample + @Test + void equalToString() { + //language=java + rewriteRun( + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.equalTo; + import static org.hamcrest.Matchers.is; + import static org.hamcrest.Matchers.not; + + class ATest { + @Test + void testEquals() { + String str1 = "Hello world!"; + String str2 = "Hello world!"; + assertThat(str1, is(equalTo(str2))); + assertThat(str1, is(not(equalTo(str2 + "!")))); + } + } + """, + """ + import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.assertEquals; + import static org.junit.jupiter.api.Assertions.assertNotEquals; + + class ATest { + @Test + void testEquals() { + String str1 = "Hello world!"; + String str2 = "Hello world!"; + assertEquals(str1, str2); + assertNotEquals(str1, str2 + "!"); + } + } + """ + ) + ); + } + + @Test + void assertWithLogicOp() { + rewriteRun( + //language=java + java( + """ + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + + class ATest { + @Test + void testEquals() { + int a = 7; + int b = 29; + assertThat("Not equal", a == b); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testEquals() { + int a = 7; + int b = 29; + assertTrue(a == b, "Not equal"); + } + } + """ + ) + ); + } + + @Test + void assertWithMethodCall() { + rewriteRun( + //language=java + java( + """ + import org.junit.jupiter.api.Test; + + import static org.hamcrest.MatcherAssert.assertThat; + + class ATest { + @Test + void testContains() { + String string = "Hello world"; + assertThat("Does not contain", string.contains("llo wor")); + } + } + """, + """ + import org.junit.jupiter.api.Test; + + import static org.junit.jupiter.api.Assertions.assertTrue; + + class ATest { + @Test + void testContains() { + String string = "Hello world"; + assertTrue(string.contains("llo wor"), "Does not contain"); + } + } + """ + ) + ); + } +} diff --git a/src/test/java/org/openrewrite/java/testing/hamcrest/RemoveNotMatcherTest.java b/src/test/java/org/openrewrite/java/testing/hamcrest/RemoveNotMatcherTest.java new file mode 100644 index 000000000..418c81a78 --- /dev/null +++ b/src/test/java/org/openrewrite/java/testing/hamcrest/RemoveNotMatcherTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.testing.hamcrest; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; +import static org.openrewrite.test.RewriteTest.toRecipe; + +class RemoveNotMatcherTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec + .parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "junit-jupiter-api-5.9", "hamcrest-2.2")) + .recipe(toRecipe(RemoveNotMatcherVisitor::new)); + } + + @DocumentExample + void nestedNotMatcher() { + rewriteRun( + //language=java + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.equalTo; + import static org.hamcrest.Matchers.not; + + class ATest { + @Test + void testEquals() { + String str1 = "Hello world!"; + String str2 = "Hello world!"; + assertThat(str1, not(equalTo(str2))); + } + } + """, + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.equalTo; + + class ATest { + @Test + void testEquals() { + String str1 = "Hello world!"; + String str2 = "Hello world!"; + assertThat(str1, equalTo(str2)); + } + } + """ + ) + ); + } + + @Test + void notMatcher() { + rewriteRun( + //language=java + java( + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.not; + + class ATest { + @Test + void testEquals() { + String str1 = "Hello world!"; + String str2 = "Hello world!"; + assertThat(str1, not(str2)); + } + } + """, + """ + import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; + import static org.hamcrest.Matchers.equalTo; + + class ATest { + @Test + void testEquals() { + String str1 = "Hello world!"; + String str2 = "Hello world!"; + assertThat(str1, equalTo(str2)); + } + } + """ + ) + ); + } + +}