diff --git a/src/main/java/org/openrewrite/java/testing/junitassertj/AssertArrayEqualsToAssertThat.java b/src/main/java/org/openrewrite/java/testing/junitassertj/AssertArrayEqualsToAssertThat.java new file mode 100644 index 000000000..5fc3d98ff --- /dev/null +++ b/src/main/java/org/openrewrite/java/testing/junitassertj/AssertArrayEqualsToAssertThat.java @@ -0,0 +1,187 @@ +/* + * Copyright 2020 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.junitassertj; + +import org.openrewrite.AutoConfigure; +import org.openrewrite.java.AutoFormat; +import org.openrewrite.java.JavaIsoRefactorVisitor; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.tree.*; + +import java.util.List; + +import static org.openrewrite.java.tree.MethodTypeBuilder.newMethodType; + +/** + * This is a refactoring visitor that will convert JUnit-style assertArrayEquals() to assertJ's assertThat().containsExactly(). + * + * This visitor will handle the following JUnit 5 method signatures: + * + *

+ *  Two parameter variants:
+ *
+ *  assertArrayEquals(expected,actual) -> assertThat(actual).containsExactly(expected)
+ *
+ *  Three parameter variant where the third argument is a String:
+ *
+ *  assertArrayEquals(expected, actual, "message") -> assertThat(actual).as("message").containsExactly(expected)
+ *
+ *  Three parameter variant where the third argument is a String supplier:
+ *
+ *  assertArrayEquals(expected, actual, () -> "message") -> assertThat(actual).withFailureMessage("message").containsExactly(expected)
+ *
+ *  Three parameter variant where args are all floating point numbers.
+ *
+ *  assertArrayEquals(expected, actual, delta) -> assertThat(actual).containsExactly(expected, within(delta));
+ *
+ *  Four parameter variant when comparing floating point numbers with a delta and a message:
+ *
+ *  assertArrayEquals(expected, actual, delta, "message") -> assertThat(actual).withFailureMessage("message").containsExactly(expected, within(delta));
+ *
+ * 
+ */ +@AutoConfigure +public class AssertArrayEqualsToAssertThat extends JavaIsoRefactorVisitor { + + private static final String JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.junit.jupiter.api.Assertions"; + + private static final String ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.assertj.core.api.Assertions"; + private static final String ASSERTJ_ASSERT_THAT_METHOD_NAME = "assertThat"; + private static final String ASSERTJ_WITHIN_METHOD_NAME = "within"; + + /** + * This matcher finds the junit methods that will be migrated by this visitor. + */ + private static final MethodMatcher JUNIT_ASSERT_EQUALS_MATCHER = new MethodMatcher( + JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME + " assertArrayEquals(..)" + ); + + private static final JavaType ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT = newMethodType() + .declaringClass("org.assertj.core.api.Assertions") + .flags(Flag.Public, Flag.Static) + .name("*") + .build(); + + public AssertArrayEqualsToAssertThat() { + setCursoringOn(); + } + + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { + + J.MethodInvocation original = super.visitMethodInvocation(method); + + if (!JUNIT_ASSERT_EQUALS_MATCHER.matches(method)) { + return original; + } + + List originalArgs = original.getArgs().getArgs(); + + Expression expected = originalArgs.get(0); + Expression actual = originalArgs.get(1); + + J.MethodInvocation replacement; + if (originalArgs.size() == 2) { + //assertThat(actual).isEqualTo(expected) + replacement = assertSimple(actual, expected); + } else if (originalArgs.size() == 3 && !isFloatingPointType(originalArgs.get(2))) { + //assertThat(actual).as(message).isEqualTo(expected) + replacement = assertWithMessage(actual, expected, originalArgs.get(2)); + } else if (originalArgs.size() == 3) { + //assert is using floating points with a delta and no message. + replacement = assertFloatingPointDelta(actual, expected, originalArgs.get(2)); + maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_WITHIN_METHOD_NAME); + + } else { + //The assertEquals is using a floating point with a delta argument and a message. + replacement = assertFloatingPointDeltaWithMessage(actual, expected, originalArgs.get(2), originalArgs.get(3)); + maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_WITHIN_METHOD_NAME); + } + + //Make sure there is a static import for "org.assertj.core.api.Assertions.assertThat" + maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_ASSERT_THAT_METHOD_NAME); + //And if there are no longer references to the JUnit assertions class, we can remove the import. + maybeRemoveImport(JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME); + + //Format the replacement method invocation in the context of where it is called. + andThen(new AutoFormat(replacement)); + return replacement; + } + + private J.MethodInvocation assertSimple(Expression actual, Expression expected) { + + List statements = treeBuilder.buildSnippet(getCursor(), + String.format("assertThat(%s).containsExactly(%s);", actual.printTrimmed(), expected.printTrimmed()), + ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT + ); + return statements.get(0); + } + + private J.MethodInvocation assertWithMessage(Expression actual, Expression expected, Expression message) { + + // In assertJ the "as" method has a more informative error message, but doesn't accept String suppliers + // so we're using "as" if the message is a string and "withFailMessage" if it is a supplier. + String messageAs = TypeUtils.isString(message.getType())?"as":"withFailMessage"; + + List statements = treeBuilder.buildSnippet(getCursor(), + String.format("assertThat(%s).%s(%s).containsExactly(%s);", + actual.printTrimmed(), messageAs, message.printTrimmed(), expected.printTrimmed()), + ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT + ); + return statements.get(0); + } + + private J.MethodInvocation assertFloatingPointDelta(Expression actual, Expression expected, Expression delta) { + List statements = treeBuilder.buildSnippet(getCursor(), + String.format("assertThat(%s).containsExactly(%s, within(%s));", + actual.printTrimmed(), expected.printTrimmed(), delta.printTrimmed()), + ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT + ); + return statements.get(0); + } + + private J.MethodInvocation assertFloatingPointDeltaWithMessage(Expression actual, Expression expected, + Expression delta, Expression message) { + + //If the message is a string use "as", if it is a supplier use "withFailMessage" + String messageAs = TypeUtils.isString(message.getType())?"as":"withFailMessage"; + + List statements = treeBuilder.buildSnippet(getCursor(), + String.format("assertThat(%s).%s(%s).containsExactly(%s, within(%s));", + actual.printTrimmed(), messageAs, message.printTrimmed(), expected.printTrimmed(), delta.printTrimmed()), + ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT + ); + return statements.get(0); + } + + /** + * Returns true if the expression's type is either a primitive float/double or their object forms Float/Double + * + * @param expression The expression parsed from the original AST. + * @return true if the type is a floating point number. + */ + private boolean isFloatingPointType(Expression expression) { + + JavaType.FullyQualified fullyQualified = TypeUtils.asFullyQualified(expression.getType()); + if (fullyQualified != null) { + String typeName = fullyQualified.getFullyQualifiedName(); + return (typeName.equals("java.lang.Double") || typeName.equals("java.lang.Float")); + } + + JavaType.Primitive parameterType = TypeUtils.asPrimitive(expression.getType()); + return parameterType == JavaType.Primitive.Double || parameterType == JavaType.Primitive.Float; + } +} diff --git a/src/main/java/org/openrewrite/java/testing/junitassertj/AssertEqualsToAssertThat.java b/src/main/java/org/openrewrite/java/testing/junitassertj/AssertEqualsToAssertThat.java index 8b59df2dc..6d54d49d4 100644 --- a/src/main/java/org/openrewrite/java/testing/junitassertj/AssertEqualsToAssertThat.java +++ b/src/main/java/org/openrewrite/java/testing/junitassertj/AssertEqualsToAssertThat.java @@ -35,9 +35,13 @@ * * assertEquals(expected,actual) -> assertThat(actual).isEqualTo(expected) * - * Three parameter variant where the third argument is either a String or String Supplier: + * Three parameter variant where the third argument is a String: * - * assertEquals(expected, actual, "message") -> assertThat(actual).withFailureMessage("message").isEqualTo(expected) + * assertEquals(expected, actual, "message") -> assertThat(actual).as("message").isEqualTo(expected) + * + * Three parameter variant where the third argument is a String supplier: + * + * assertEquals(expected, actual, () -> "message") -> assertThat(actual).withFailureMessage("message").isEqualTo(expected) * * Three parameter variant where args are all floating point numbers. * @@ -45,7 +49,7 @@ * * Four parameter variant when comparing floating point numbers with a delta and a message: * - * assertEquals(expected, actual, delta) -> assertThat(actual).withFailureMessage("message").isCloseTo(expected, within(delta)); + * assertEquals(expected, actual, delta, "message") -> assertThat(actual).withFailureMessage("message").isCloseTo(expected, within(delta)); * * */ @@ -59,7 +63,7 @@ public class AssertEqualsToAssertThat extends JavaIsoRefactorVisitor { private static final String ASSERTJ_WITHIN_METHOD_NAME = "within"; /** - * This matcher uses a pointcut expression to find the matching junit methods that will be migrated by this visitor + * This matcher finds the junit methods that will be migrated by this visitor. */ private static final MethodMatcher JUNIT_ASSERT_EQUALS_MATCHER = new MethodMatcher( JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME + " assertEquals(..)" @@ -75,12 +79,6 @@ public AssertEqualsToAssertThat() { setCursoringOn(); } - @Override - public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu) { - maybeRemoveImport(JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME); - return super.visitCompilationUnit(cu); - } - @Override public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { @@ -107,14 +105,15 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_WITHIN_METHOD_NAME); } else { - //The assertEquals is using a primitive floating point with a delta argument. (There may be an optional) - //fourth argument that contains the message. + //The assertEquals is using a floating point with a delta argument and a message. replacement = assertFloatingPointDeltaWithMessage(actual, expected, originalArgs.get(2), originalArgs.get(3)); maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_WITHIN_METHOD_NAME); } //Make sure there is a static import for "org.assertj.core.api.Assertions.assertThat" maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_ASSERT_THAT_METHOD_NAME); + //And if there are no longer references to the JUnit assertions class, we can remove the import. + maybeRemoveImport(JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME); //Format the replacement method invocation in the context of where it is called. andThen(new AutoFormat(replacement)); @@ -131,9 +130,14 @@ private J.MethodInvocation assertSimple(Expression actual, Expression expected) } private J.MethodInvocation assertWithMessage(Expression actual, Expression expected, Expression message) { + + // In assertJ the "as" method has a more informative error message, but doesn't accept String suppliers + // so we're using "as" if the message is a string and "withFailMessage" if it is a supplier. + String messageAs = TypeUtils.isString(message.getType())?"as":"withFailMessage"; + List statements = treeBuilder.buildSnippet(getCursor(), - String.format("assertThat(%s).withFailMessage(%s).isEqualTo(%s);", - actual.printTrimmed(), message.printTrimmed(), expected.printTrimmed()), + String.format("assertThat(%s).%s(%s).isEqualTo(%s);", + actual.printTrimmed(), messageAs, message.printTrimmed(), expected.printTrimmed()), ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT ); return statements.get(0); @@ -150,21 +154,32 @@ private J.MethodInvocation assertFloatingPointDelta(Expression actual, Expressio private J.MethodInvocation assertFloatingPointDeltaWithMessage(Expression actual, Expression expected, Expression delta, Expression message) { + + //If the message is a string use "as", if it is a supplier use "withFailMessage" + String messageAs = TypeUtils.isString(message.getType())?"as":"withFailMessage"; + List statements = treeBuilder.buildSnippet(getCursor(), - String.format("assertThat(%s).withFailMessage(%s).isCloseTo(%s, within(%s));", - actual.printTrimmed(), message.printTrimmed(), expected.printTrimmed(), delta.printTrimmed()), + String.format("assertThat(%s).%s(%s).isCloseTo(%s, within(%s));", + actual.printTrimmed(), messageAs, message.printTrimmed(), expected.printTrimmed(), delta.printTrimmed()), ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT ); return statements.get(0); } /** - * Returns true if the expression's type is either a primitive float or double. + * Returns true if the expression's type is either a primitive float/double or their object forms Float/Double * * @param expression The expression parsed from the original AST. * @return true if the type is a floating point number. */ private boolean isFloatingPointType(Expression expression) { + + JavaType.FullyQualified fullyQualified = TypeUtils.asFullyQualified(expression.getType()); + if (fullyQualified != null) { + String typeName = fullyQualified.getFullyQualifiedName(); + return (typeName.equals("java.lang.Double") || typeName.equals("java.lang.Float")); + } + JavaType.Primitive parameterType = TypeUtils.asPrimitive(expression.getType()); return parameterType == JavaType.Primitive.Double || parameterType == JavaType.Primitive.Float; } diff --git a/src/main/java/org/openrewrite/java/testing/junitassertj/AssertFalseToAssertThat.java b/src/main/java/org/openrewrite/java/testing/junitassertj/AssertFalseToAssertThat.java index dfeec9bba..edef091e7 100644 --- a/src/main/java/org/openrewrite/java/testing/junitassertj/AssertFalseToAssertThat.java +++ b/src/main/java/org/openrewrite/java/testing/junitassertj/AssertFalseToAssertThat.java @@ -19,10 +19,7 @@ import org.openrewrite.java.AutoFormat; import org.openrewrite.java.JavaIsoRefactorVisitor; import org.openrewrite.java.MethodMatcher; -import org.openrewrite.java.tree.Expression; -import org.openrewrite.java.tree.Flag; -import org.openrewrite.java.tree.J; -import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.*; import java.util.Collections; import java.util.List; @@ -39,7 +36,7 @@ * *
  *     assertFalse(boolean condition) -> assertThat(condition).isFalse()
- *     assertFalse(boolean condition, String message) -> assertThat(condition).withFailMessage(message).isFalse();
+ *     assertFalse(boolean condition, String message) -> assertThat(condition).as(message).isFalse();
  *     assertFalse(boolean condition, Supplier messageSupplier) -> assertThat(condition).withFailMessage(messageSupplier).isFalse();
  * 
* @@ -51,15 +48,15 @@ @AutoConfigure public class AssertFalseToAssertThat extends JavaIsoRefactorVisitor { - private static final String JUNIT_QUALIFIED_ASSERTIONS_CLASS = "org.junit.jupiter.api.Assertions"; + private static final String JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.junit.jupiter.api.Assertions"; private static final String ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.assertj.core.api.Assertions"; private static final String ASSERTJ_ASSERT_THAT_METHOD_NAME = "assertThat"; /** - * This matcher uses a pointcut expression to find the matching junit methods that will be migrated by this visitor + * This matcher finds the junit methods that will be migrated by this visitor. */ private static final MethodMatcher JUNIT_ASSERT_FALSE_MATCHER = new MethodMatcher( - JUNIT_QUALIFIED_ASSERTIONS_CLASS + " assertFalse(boolean, ..)" + JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME + " assertFalse(boolean, ..)" ); private static final JavaType.Method ASSERTJ_ASSERT_THAT_METHOD_TYPE = newMethodType() @@ -70,14 +67,6 @@ public class AssertFalseToAssertThat extends JavaIsoRefactorVisitor { .parameter(JavaType.Primitive.Boolean, "arg1") .build(); - - @Override - public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu) { - - maybeRemoveImport(JUNIT_QUALIFIED_ASSERTIONS_CLASS); - return super.visitCompilationUnit(cu); - } - @Override public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { J.MethodInvocation original = super.visitMethodInvocation(method); @@ -104,10 +93,27 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { ASSERTJ_ASSERT_THAT_METHOD_TYPE, EMPTY ); - if (message != null) { - //If the assertFalse is the two-argument variant, we need to maintain the message via a chained method - //call to "withFailMessage". The message may be a String or Supplier and withFailMessage has - //overloads for both types. + + // In assertJ the "as" method has a more informative error message, but doesn't accept String suppliers + // so we're using "as" if the message is a string and "withFailMessage" if it is a supplier. + if (message != null && TypeUtils.isString(message.getType())) { + //If this is the three-argument variant and the third argument is a string, chain an ".as(message)" + assertSelect = new J.MethodInvocation( + randomId(), + assertSelect, //assertThat is the select for this method. + null, + J.Ident.build(randomId(), "as", null, EMPTY), + new J.MethodInvocation.Arguments( + randomId(), + Collections.singletonList(message.withPrefix("")), + EMPTY + ), + null, + EMPTY + ); + } else if (message != null) { + //If this is the three-argument variant and the third argument is a string supplier, chain the + //message ".withFailMessage(message)". "as" does not support passing a string supplier (at this time) assertSelect = new J.MethodInvocation( randomId(), assertSelect, //assertThat is the select for this method. @@ -143,6 +149,9 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { //Make sure there is a static import for "org.assertj.core.api.Assertions.assertThat" maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_ASSERT_THAT_METHOD_NAME); + //And if there are no longer references to the JUnit assertions class, we can remove the import. + maybeRemoveImport(JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME); + //Format the replacement method invocation in the context of where it is called. andThen(new AutoFormat(replacement)); return replacement; diff --git a/src/main/java/org/openrewrite/java/testing/junitassertj/AssertNotEqualsToAssertThat.java b/src/main/java/org/openrewrite/java/testing/junitassertj/AssertNotEqualsToAssertThat.java new file mode 100644 index 000000000..f72ed42a8 --- /dev/null +++ b/src/main/java/org/openrewrite/java/testing/junitassertj/AssertNotEqualsToAssertThat.java @@ -0,0 +1,188 @@ +/* + * Copyright 2020 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.junitassertj; + +import org.openrewrite.AutoConfigure; +import org.openrewrite.internal.lang.Nullable; +import org.openrewrite.java.AutoFormat; +import org.openrewrite.java.JavaIsoRefactorVisitor; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.tree.*; + +import java.util.List; + +import static org.openrewrite.java.tree.MethodTypeBuilder.newMethodType; + +/** + * This is a refactoring visitor that will convert JUnit-style assertNotEquals() to assertJ's assertThat().isNotEqualTo(). + * + * This visitor has to convert a surprisingly large number (93 methods) of JUnit's assertEquals to assertThat(). + * + *

+ *  Two parameter variants:
+ *
+ *  assertNotEquals(expected,actual) -> assertThat(actual).isNotEqualTo(expected)
+ *
+ *  Three parameter variant where the third argument is a String:
+ *
+ *  assertNotEquals(expected, actual, "message") -> assertThat(actual).as("message").isNotEqualTo(expected)
+ *
+ *  Three parameter variant where the third argument is a String Supplier (there is no overloaded "as" method that takes a supplier):
+ *
+ *  assertNotEquals(expected, actual, "message") -> assertThat(actual).withFailMessage("message").isNotEqualTo(expected)
+ *
+ *  Three parameter variant where args are all floating point numbers.
+ *
+ *  assertEquals(expected, actual, delta) -> assertThat(actual).isCloseTo(expected, within(delta));
+ *
+ *  Four parameter variant when comparing floating point numbers with a delta and a message:
+ *
+ *  assertEquals(expected, actual, delta, "message") -> assertThat(actual).withFailureMessage("message").isCloseTo(expected, within(delta));
+ *
+ * 
+ */ +@AutoConfigure +public class AssertNotEqualsToAssertThat extends JavaIsoRefactorVisitor { + + private static final String JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.junit.jupiter.api.Assertions"; + + private static final String ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.assertj.core.api.Assertions"; + private static final String ASSERTJ_ASSERT_THAT_METHOD_NAME = "assertThat"; + private static final String ASSERTJ_WITHIN_METHOD_NAME = "within"; + + /** + * This matcher finds the junit methods that will be migrated by this visitor. + */ + private static final MethodMatcher JUNIT_ASSERT_EQUALS_MATCHER = new MethodMatcher( + JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME + " assertNotEquals(..)" + ); + + private static final JavaType ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT = newMethodType() + .declaringClass("org.assertj.core.api.Assertions") + .flags(Flag.Public, Flag.Static) + .name("*") + .build(); + + public AssertNotEqualsToAssertThat() { + setCursoringOn(); + } + + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { + + J.MethodInvocation original = super.visitMethodInvocation(method); + if (!JUNIT_ASSERT_EQUALS_MATCHER.matches(method)) { + return original; + } + + List originalArgs = original.getArgs().getArgs(); + + Expression expected = originalArgs.get(0); + Expression actual = originalArgs.get(1); + + J.MethodInvocation replacement; + if (originalArgs.size() == 2) { + //assertThat(actual).isNotEqualTo(expected) + replacement = assertSimple(actual, expected); + } else if (originalArgs.size() == 3 && !isFloatingPointType(originalArgs.get(2))) { + //assertThat(actual).as(message).isNotEqualTo(expected) + replacement = assertWithMessage(actual, expected, originalArgs.get(2)); + } else if (originalArgs.size() == 3) { + //assertThat(actual).isNotCloseTo(expected, within(delta)) + replacement = assertFloatingPointDelta(actual, expected, originalArgs.get(2)); + maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_WITHIN_METHOD_NAME); + + } else { + //assertThat(actual).as(message).isNotCloseTo(expected, within(delta)) + replacement = assertFloatingPointDeltaWithMessage(actual, expected, originalArgs.get(2), originalArgs.get(3)); + maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_WITHIN_METHOD_NAME); + } + + //Make sure there is a static import for "org.assertj.core.api.Assertions.assertThat" + maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_ASSERT_THAT_METHOD_NAME); + //And if there are no longer references to the JUnit assertions class, we can remove the import. + maybeRemoveImport(JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME); + + //Format the replacement method invocation in the context of where it is called. + andThen(new AutoFormat(replacement)); + return replacement; + } + + private J.MethodInvocation assertSimple(Expression actual, Expression expected) { + + List statements = treeBuilder.buildSnippet(getCursor(), + String.format("assertThat(%s).isNotEqualTo(%s);", actual.printTrimmed(), expected.printTrimmed()), + ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT + ); + return statements.get(0); + } + + private J.MethodInvocation assertWithMessage(Expression actual, Expression expected, Expression message) { + + // In assertJ the "as" method has a more informative error message, but doesn't accept String suppliers + // so we're using "as" if the message is a string and "withFailMessage" if it is a supplier. + String messageAs = TypeUtils.isString(message.getType())?"as":"withFailMessage"; + + List statements = treeBuilder.buildSnippet(getCursor(), + String.format("assertThat(%s).%s(%s).isNotEqualTo(%s);", + actual.printTrimmed(), messageAs, message.printTrimmed(), expected.printTrimmed()), + ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT + ); + return statements.get(0); + } + + private J.MethodInvocation assertFloatingPointDelta(Expression actual, Expression expected, Expression delta) { + List statements = treeBuilder.buildSnippet(getCursor(), + String.format("assertThat(%s).isNotCloseTo(%s, within(%s));", + actual.printTrimmed(), expected.printTrimmed(), delta.printTrimmed()), + ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT + ); + return statements.get(0); + } + + private J.MethodInvocation assertFloatingPointDeltaWithMessage(Expression actual, Expression expected, + Expression delta, Expression message) { + + //If the message is a string use "as", if it is a supplier use "withFailMessage" + String messageAs = TypeUtils.isString(message.getType())?"as":"withFailMessage"; + + List statements = treeBuilder.buildSnippet(getCursor(), + String.format("assertThat(%s).%s(%s).isNotCloseTo(%s, within(%s));", + actual.printTrimmed(), messageAs, message.printTrimmed(), expected.printTrimmed(), delta.printTrimmed()), + ASSERTJ_ASSERTIONS_WILDCARD_STATIC_IMPORT + ); + return statements.get(0); + } + + /** + * Returns true if the expression's type is either a primitive float/double or their object forms Float/Double + * + * @param expression The expression parsed from the original AST. + * @return true if the type is a floating point number. + */ + private boolean isFloatingPointType(Expression expression) { + + JavaType.FullyQualified fullyQualified = TypeUtils.asFullyQualified(expression.getType()); + if (fullyQualified != null) { + String typeName = fullyQualified.getFullyQualifiedName(); + return (typeName.equals("java.lang.Double") || typeName.equals("java.lang.Float")); + } + + JavaType.Primitive parameterType = TypeUtils.asPrimitive(expression.getType()); + return parameterType == JavaType.Primitive.Double || parameterType == JavaType.Primitive.Float; + } + +} diff --git a/src/main/java/org/openrewrite/java/testing/junitassertj/AssertTrueToAssertThat.java b/src/main/java/org/openrewrite/java/testing/junitassertj/AssertTrueToAssertThat.java index 89b315d98..a53355363 100644 --- a/src/main/java/org/openrewrite/java/testing/junitassertj/AssertTrueToAssertThat.java +++ b/src/main/java/org/openrewrite/java/testing/junitassertj/AssertTrueToAssertThat.java @@ -17,10 +17,7 @@ import org.openrewrite.AutoConfigure; import org.openrewrite.java.*; -import org.openrewrite.java.tree.Expression; -import org.openrewrite.java.tree.Flag; -import org.openrewrite.java.tree.J; -import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.*; import java.util.Collections; import java.util.List; @@ -49,15 +46,15 @@ @AutoConfigure public class AssertTrueToAssertThat extends JavaIsoRefactorVisitor { - private static final String JUNIT_QUALIFIED_ASSERTIONS_CLASS = "org.junit.jupiter.api.Assertions"; + private static final String JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.junit.jupiter.api.Assertions"; private static final String ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.assertj.core.api.Assertions"; private static final String ASSERTJ_ASSERT_THAT_METHOD_NAME = "assertThat"; /** - * This matcher uses a pointcut expression to find the matching junit methods that will be migrated by this visitor + * This matcher finds the junit methods that will be migrated by this visitor. */ private static final MethodMatcher JUNIT_ASSERT_TRUE_MATCHER = new MethodMatcher( - JUNIT_QUALIFIED_ASSERTIONS_CLASS + " assertTrue(boolean, ..)" + JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME + " assertTrue(boolean, ..)" ); private static final JavaType.Method assertThatMethodType = newMethodType() @@ -68,13 +65,6 @@ public class AssertTrueToAssertThat extends JavaIsoRefactorVisitor { .parameter(JavaType.Primitive.Boolean, "arg1") .build(); - @Override - public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu) { - - maybeRemoveImport(JUNIT_QUALIFIED_ASSERTIONS_CLASS); - return super.visitCompilationUnit(cu); - } - @Override public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { J.MethodInvocation original = super.visitMethodInvocation(method); @@ -82,7 +72,6 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { return original; } - List originalArgs = original.getArgs().getArgs(); Expression condition = originalArgs.get(0); Expression message = originalArgs.size() == 2 ? originalArgs.get(1):null; @@ -102,10 +91,26 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { assertThatMethodType, EMPTY ); - if (message != null) { - //If the assertTrue is the two-argument variant, we need to maintain the message via a chained method - //call to "withFailMessage". There message may be a String or Supplier and withFailMessage has - //overloads for both types. + + // In assertJ the "as" method has a more informative error message, but doesn't accept String suppliers + // so we're using "as" if the message is a string and "withFailMessage" if it is a supplier. + if (message != null && TypeUtils.isString(message.getType())) { + //If this is the three-argument variant and the third argument is a string + assertSelect = new J.MethodInvocation( + randomId(), + assertSelect, //assertThat is the select for this method. + null, + J.Ident.build(randomId(), "as", null, EMPTY), + new J.MethodInvocation.Arguments( + randomId(), + Collections.singletonList(message.withPrefix("")), + EMPTY + ), + null, + EMPTY + ); + } else if (message != null) { + //If this is the three-argument variant and the third argument is a string supplier assertSelect = new J.MethodInvocation( randomId(), assertSelect, //assertThat is the select for this method. @@ -141,6 +146,9 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) { //Make sure there is a static import for "org.assertj.core.api.Assertions.assertThat" maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, ASSERTJ_ASSERT_THAT_METHOD_NAME); + //And if there are no longer references to the JUnit assertions class, we can remove the import. + maybeRemoveImport(JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME); + //Format the replacement method invocation in the context of where it is called. andThen(new AutoFormat(replacement)); return replacement; diff --git a/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertArrayEqualsToAssertThatTest.kt b/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertArrayEqualsToAssertThatTest.kt new file mode 100644 index 000000000..4c8e593ce --- /dev/null +++ b/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertArrayEqualsToAssertThatTest.kt @@ -0,0 +1,325 @@ +/* + * Copyright 2020 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.junitassertj + +import org.junit.jupiter.api.Test +import org.openrewrite.Parser +import org.openrewrite.RefactorVisitor +import org.openrewrite.RefactorVisitorTestForParser +import org.openrewrite.java.JavaParser +import org.openrewrite.java.tree.J + +class AssertArrayEqualsToAssertThatTest: RefactorVisitorTestForParser { + override val parser: Parser = JavaParser.fromJavaVersion() + .classpath("junit", "assertj-core", "apiguardian-api") + .build() + + override val visitors: Iterable> = listOf(AssertArrayEqualsToAssertThat()) + + @Test + fun singleStaticMethodNoMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertArrayEquals; + + public class A { + + @Test + public void test() { + Integer[] expected = new Integer[] {1, 2, 3}; + assertArrayEquals(expected, notification()); + } + private Integer[] notification() { + return new Integer[] {1, 2, 3}; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + + public class A { + + @Test + public void test() { + Integer[] expected = new Integer[] {1, 2, 3}; + assertThat(notification()).containsExactly(expected); + } + private Integer[] notification() { + return new Integer[] {1, 2, 3}; + } + } + """ + ) + + @Test + fun singleStaticMethodWithMessageLambda() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertArrayEquals; + + public class A { + + @Test + public void test() { + assertArrayEquals(new int[] {1, 2, 3}, notification(), () -> "These arrays should be equal"); + } + private int[] notification() { + return new int[] {1, 2, 3}; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + + public class A { + + @Test + public void test() { + assertThat(notification()).withFailMessage(() -> "These arrays should be equal").containsExactly(new int[] {1, 2, 3}); + } + private int[] notification() { + return new int[] {1, 2, 3}; + } + } + """ + ) + + @Test + fun doublesWithinNoMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertArrayEquals; + + public class A { + + @Test + public void test() { + assertArrayEquals(new double[] {1.0d, 2.0d, 3.0d}, notification(), .2d); + } + private double[] notification() { + return new double[] {1.1d, 2.1d, 3.1d}; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.assertj.core.api.Assertions.within; + + public class A { + + @Test + public void test() { + assertThat(notification()).containsExactly(new double[] {1.0d, 2.0d, 3.0d}, within(.2d)); + } + private double[] notification() { + return new double[] {1.1d, 2.1d, 3.1d}; + } + } + """ + ) + + @Test + fun doublesWithinAndWithMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertArrayEquals; + + public class A { + + @Test + public void test() { + assertArrayEquals(new double[] {1.0d, 2.0d, 3.0d}, notification(), .2d, "These should be close"); + } + private double[] notification() { + return new double[] {1.1d, 2.1d, 3.1d}; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.assertj.core.api.Assertions.within; + + public class A { + + @Test + public void test() { + assertThat(notification()).as("These should be close").containsExactly(new double[] {1.0d, 2.0d, 3.0d}, within(.2d)); + } + private double[] notification() { + return new double[] {1.1d, 2.1d, 3.1d}; + } + } + """ + ) + + @Test + fun doublesObjectsWithMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertArrayEquals; + + public class A { + + @Test + public void test() { + assertArrayEquals(new Double[] {1.0d, 2.0d, 3.0d}, notification(), "These arrays should be equal"); + } + private Double[] notification() { + return new Double[] {1.0d, 2.0d, 3.0d}; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + + public class A { + + @Test + public void test() { + assertThat(notification()).as("These arrays should be equal").containsExactly(new Double[] {1.0d, 2.0d, 3.0d}); + } + private Double[] notification() { + return new Double[] {1.0d, 2.0d, 3.0d}; + } + } + """ + ) + + @Test + fun floatCloseToWithNoMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertArrayEquals; + + public class A { + + @Test + public void test() { + assertArrayEquals(new float[] {1.0f, 2.0f, 3.0f}, notification(), .2f); + } + private float[] notification() { + return new float[] {1.1f, 2.1f, 3.1f}; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.assertj.core.api.Assertions.within; + + public class A { + + @Test + public void test() { + assertThat(notification()).containsExactly(new float[] {1.0f, 2.0f, 3.0f}, within(.2f)); + } + private float[] notification() { + return new float[] {1.1f, 2.1f, 3.1f}; + } + } + """ + ) + + @Test + fun floatCloseToWithMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertArrayEquals; + + public class A { + + @Test + public void test() { + assertArrayEquals(new float[] {1.0f, 2.0f, 3.0f}, notification(), .2f, () -> "These should be close"); + } + private float[] notification() { + return new float[] {1.1f, 2.1f, 3.1f}; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.assertj.core.api.Assertions.within; + + public class A { + + @Test + public void test() { + assertThat(notification()).withFailMessage(() -> "These should be close").containsExactly(new float[] {1.0f, 2.0f, 3.0f}, within(.2f)); + } + private float[] notification() { + return new float[] {1.1f, 2.1f, 3.1f}; + } + } + """ + ) + + @Test + fun fullyQualifiedMethodWithMessage() = assertRefactored( + before = """ + import org.junit.Test; + + public class A { + + @Test + public void test() { + String[] expected = new String[] {"Fred", "Alice", "Mary"}; + org.junit.jupiter.api.Assertions.assertArrayEquals(expected, notification(), () -> "These should be close"); + } + private String[] notification() { + return new String[] {"Fred", "Alice", "Mary"}; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + + public class A { + + @Test + public void test() { + String[] expected = new String[] {"Fred", "Alice", "Mary"}; + assertThat(notification()).withFailMessage(() -> "These should be close").containsExactly(expected); + } + private String[] notification() { + return new String[] {"Fred", "Alice", "Mary"}; + } + } + """ + ) +} \ No newline at end of file diff --git a/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertEqualsToAssertThatTest.kt b/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertEqualsToAssertThatTest.kt index 195d45f55..a7dde43c6 100644 --- a/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertEqualsToAssertThatTest.kt +++ b/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertEqualsToAssertThatTest.kt @@ -76,7 +76,7 @@ class AssertEqualsToAssertThatTest: RefactorVisitorTestForParser "These should be equal"); } private String notification() { return "fred"; @@ -92,7 +92,7 @@ class AssertEqualsToAssertThatTest: RefactorVisitorTestForParser "These should be equal").isEqualTo("fred"); } private String notification() { return "fred"; @@ -166,7 +166,7 @@ class AssertEqualsToAssertThatTest: RefactorVisitorTestForParser "These should be close."); + } + private double notification() { + return Double.valueOf(0.1d); + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.assertj.core.api.Assertions.within; + + public class A { + + @Test + public void test() { + assertThat(notification()).withFailMessage(() -> "These should be close.").isCloseTo(Double.valueOf(0.0d), within(Double.valueOf(0.2d))); + } + private double notification() { + return Double.valueOf(0.1d); + } + } + """ + ) + @Test fun floatCloseToWithNoMessage() = assertRefactored( before = """ @@ -240,7 +277,7 @@ class AssertEqualsToAssertThatTest: RefactorVisitorTestForParser 0).withFailMessage("The notification should be negative").isFalse(); + assertThat(notification() != null && notification() > 0).as("The notification should be negative").isFalse(); } private Integer notification() { return 1; @@ -165,7 +165,7 @@ class AssertFalseToAssertThatTest: RefactorVisitorTestForParser 0).isFalse(); - assertThat(notification() != null && notification() > 0).withFailMessage("The notification should be negative").isFalse(); + assertThat(notification() != null && notification() > 0).as("The notification should be negative").isFalse(); assertThat(notification() != null && notification() > 0).withFailMessage(() -> "The notification should be negative").isFalse(); } private Integer notification() { @@ -206,7 +206,7 @@ class AssertFalseToAssertThatTest: RefactorVisitorTestForParser 0).isFalse(); - assertThat(notification() != null && notification() > 0).withFailMessage("The notification should be negative").isFalse(); + assertThat(notification() != null && notification() > 0).as("The notification should be negative").isFalse(); assertThat(notification() != null && notification() > 0).withFailMessage(() -> "The notification should be negative").isFalse(); } private Integer notification() { @@ -250,7 +250,7 @@ class AssertFalseToAssertThatTest: RefactorVisitorTestForParser 0).isFalse(); - assertThat(notification() != null && notification() > 0).withFailMessage("The notification should be negative").isFalse(); + assertThat(notification() != null && notification() > 0).as("The notification should be negative").isFalse(); assertThat(notification() != null && notification() > 0).withFailMessage(() -> "The notification should be negative").isFalse(); assertFalse(() -> notification() != null && notification() > 0); assertFalse(() -> notification() != null && notification() > 0, "The notification should be negative"); diff --git a/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertNotEqualsToAssertThatTest.kt b/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertNotEqualsToAssertThatTest.kt new file mode 100644 index 000000000..2bfc39a8b --- /dev/null +++ b/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertNotEqualsToAssertThatTest.kt @@ -0,0 +1,326 @@ +/* + * Copyright 2020 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.junitassertj + +import org.junit.jupiter.api.Test +import org.openrewrite.Parser +import org.openrewrite.RefactorVisitor +import org.openrewrite.RefactorVisitorTestForParser +import org.openrewrite.java.JavaParser +import org.openrewrite.java.tree.J + +class AssertNotEqualsToAssertThatTest: RefactorVisitorTestForParser { + override val parser: Parser = JavaParser.fromJavaVersion() + .classpath("junit", "assertj-core", "apiguardian-api") + .build() + + override val visitors: Iterable> = listOf(AssertNotEqualsToAssertThat()) + + @Test + fun singleStaticMethodNoMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertNotEquals; + + public class A { + + @Test + public void test() { + assertNotEquals(1, notification()); + } + private Integer notification() { + return 2; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + + public class A { + + @Test + public void test() { + assertThat(notification()).isNotEqualTo(1); + } + private Integer notification() { + return 2; + } + } + """ + ) + + @Test + fun singleStaticMethodWithMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertNotEquals; + + public class A { + + @Test + public void test() { + assertNotEquals("fred", notification(), () -> "These should not be equal"); + } + private String notification() { + return "joe"; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + + public class A { + + @Test + public void test() { + assertThat(notification()).withFailMessage(() -> "These should not be equal").isNotEqualTo("fred"); + } + private String notification() { + return "joe"; + } + } + """ + ) + + @Test + fun doubleCloseToWithNoMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertNotEquals; + + public class A { + + @Test + public void test() { + assertNotEquals(0.0d, notification(), 0.2d); + } + private Double notification() { + return 1.1d; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.assertj.core.api.Assertions.within; + + public class A { + + @Test + public void test() { + assertThat(notification()).isNotCloseTo(0.0d, within(0.2d)); + } + private Double notification() { + return 1.1d; + } + } + """ + ) + + @Test + fun doubleCloseToWithMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertNotEquals; + + public class A { + + @Test + public void test() { + assertNotEquals(2.0d, notification(), 0.2d, "These should not be close."); + } + private double notification() { + return 0.1d; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.assertj.core.api.Assertions.within; + + public class A { + + @Test + public void test() { + assertThat(notification()).as("These should not be close.").isNotCloseTo(2.0d, within(0.2d)); + } + private double notification() { + return 0.1d; + } + } + """ + ) + + @Test + fun doubleObjectsCloseToWithMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertNotEquals; + + public class A { + + @Test + public void test() { + assertNotEquals(Double.valueOf(0.0d), notification(), Double.valueOf(0.2d), () -> "These should not be close."); + } + private double notification() { + return Double.valueOf(1.1d); + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.assertj.core.api.Assertions.within; + + public class A { + + @Test + public void test() { + assertThat(notification()).withFailMessage(() -> "These should not be close.").isNotCloseTo(Double.valueOf(0.0d), within(Double.valueOf(0.2d))); + } + private double notification() { + return Double.valueOf(1.1d); + } + } + """ + ) + + @Test + fun floatCloseToWithNoMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertNotEquals; + + public class A { + + @Test + public void test() { + assertNotEquals(2.0f, notification(), 0.2f); + } + private Float notification() { + return 0.1f; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.assertj.core.api.Assertions.within; + + public class A { + + @Test + public void test() { + assertThat(notification()).isNotCloseTo(2.0f, within(0.2f)); + } + private Float notification() { + return 0.1f; + } + } + """ + ) + + @Test + fun floatCloseToWithMessage() = assertRefactored( + before = """ + import org.junit.Test; + + import static org.junit.jupiter.api.Assertions.assertNotEquals; + + public class A { + + @Test + public void test() { + assertNotEquals(2.0f, notification(), 0.2f, "These should not be close."); + } + private float notification() { + return 0.1f; + } + } + """, + after = """ + import org.junit.Test; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.assertj.core.api.Assertions.within; + + public class A { + + @Test + public void test() { + assertThat(notification()).as("These should not be close.").isNotCloseTo(2.0f, within(0.2f)); + } + private float notification() { + return 0.1f; + } + } + """ + ) + + @Test + fun fullyQualifiedMethodWithMessage() = assertRefactored( + before = """ + import java.io.File; + import org.junit.Test; + + public class A { + + @Test + public void test() { + org.junit.jupiter.api.Assertions.assertNotEquals(new File("otherFile"), notification(), "These should not be equal"); + } + private File notification() { + return new File("someFile"); + } + } + """, + after = """ + import org.junit.Test; + + import java.io.File; + + import static org.assertj.core.api.Assertions.assertThat; + + public class A { + + @Test + public void test() { + assertThat(notification()).as("These should not be equal").isNotEqualTo(new File("otherFile")); + } + private File notification() { + return new File("someFile"); + } + } + """ + ) + +} \ No newline at end of file diff --git a/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertTrueToAssertThatTest.kt b/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertTrueToAssertThatTest.kt index ab6f37f42..99267e954 100644 --- a/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertTrueToAssertThatTest.kt +++ b/src/test/kotlin/org/openrewrite/java/testing/junitassertj/AssertTrueToAssertThatTest.kt @@ -92,7 +92,7 @@ class AssertTrueToAssertThatTest: RefactorVisitorTestForParser 0).withFailMessage("The notification should be positive").isTrue(); + assertThat(notification() != null && notification() > 0).as("The notification should be positive").isTrue(); } private Integer notification() { return 1; @@ -165,7 +165,7 @@ class AssertTrueToAssertThatTest: RefactorVisitorTestForParser 0).isTrue(); - assertThat(notification() != null && notification() > 0).withFailMessage("The notification should be positive").isTrue(); + assertThat(notification() != null && notification() > 0).as("The notification should be positive").isTrue(); assertThat(notification() != null && notification() > 0).withFailMessage(() -> "The notification should be positive").isTrue(); } private Integer notification() { @@ -206,7 +206,7 @@ class AssertTrueToAssertThatTest: RefactorVisitorTestForParser 0).isTrue(); - assertThat(notification() != null && notification() > 0).withFailMessage("The notification should be positive").isTrue(); + assertThat(notification() != null && notification() > 0).as("The notification should be positive").isTrue(); assertThat(notification() != null && notification() > 0).withFailMessage(() -> "The notification should be positive").isTrue(); } private Integer notification() { @@ -251,7 +251,7 @@ class AssertTrueToAssertThatTest: RefactorVisitorTestForParser 0).isTrue(); - assertThat(notification() != null && notification() > 0).withFailMessage("The notification should be positive").isTrue(); + assertThat(notification() != null && notification() > 0).as("The notification should be positive").isTrue(); assertThat(notification() != null && notification() > 0).withFailMessage(() -> "The notification should be positive").isTrue(); assertTrue(() -> notification() != null && notification() > 0); assertTrue(() -> notification() != null && notification() > 0, "The notification should be positive");