diff --git a/README.md b/README.md index 688e3d9..9f0cfbe 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Then AssertJ would tell you the _actual contents_ of the collection on failure. ## Conversion of JUnit assertions to AssertJ -The plugin also supports the conversion of the most common JUnit 4 assertions to AssertJ. +The plugin also supports the conversion of the most common JUnit 4 and JUnit 5 assertions to AssertJ. ## Wrong use of AssertJ @@ -694,7 +694,7 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the However, this suggests that the test has actually been run and passed instead of showing the test as being skipped. - Return statements in ```if``` statements in main test methods (must be annotated with JUnit 4 or + Return statements in ```if``` statements in main test methods (must be annotated with JUnit 4 or JUnit 5 or Jupiter ```@Test``` annotations) will be verified to have at least one ```assertThat()``` statement in the code flow. Method calls within the same class will be examined for ```assertThat()``` statements, too. However, at most 50 statements and down to five recursions will be tolerated before giving up. @@ -731,7 +731,7 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the - JUnitAssertToAssertJ - Tries to convert most of the JUnit 4 assertions and assumptions to AssertJ format. + Tries to convert most of the JUnit 4 and JUnit 5 assertions and assumptions to AssertJ format. Sometimes the expected and actual expressions are specified in wrong order -- Cajon tries to swap these when it detects the supposed actual expression to be a constant while the expected one is not. @@ -817,6 +817,10 @@ Feel free to use the code (in package ```de.platon42.intellij.jupiter```) for yo ## Changelog +#### V1.13 (unreleased) + +- Added support for converting JUnit 5 tests to AssertJ + ### V1.12 (06-May-21) - Maintenance. Updated various dependencies (Kotlin 1.50.0) and AssertJ 3.19.0 diff --git a/build.gradle b/build.gradle index 15d3dee..353db0b 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { } group 'de.platon42' -version '1.12' +version '1.12.1' sourceCompatibility = "1.8" targetCompatibility = "1.8" @@ -48,10 +48,9 @@ intellij { patchPluginXml { setChangeNotes(""" -
Full changelog available at Github project site.
""") diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractJUnitAssertInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractJUnitAssertInspection.kt index dfe8a42..b93899f 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractJUnitAssertInspection.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/AbstractJUnitAssertInspection.kt @@ -10,9 +10,15 @@ abstract class AbstractJUnitAssertInspection : AbstractBaseJavaLocalInspectionTo @NonNls const val JUNIT4_ASSERT_CLASSNAME = "org.junit.Assert" + @NonNls + const val JUNIT5_ASSERT_CLASSNAME = "org.junit.jupiter.api.Assertions" + @NonNls const val JUNIT4_ASSUME_CLASSNAME = "org.junit.Assume" + @NonNls + const val JUNIT5_ASSUME_CLASSNAME = "org.junit.jupiter.api.Assumptions" + @NonNls const val ASSERT_TRUE_METHOD = "assertTrue" diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JUnitAssertToAssertJInspection.kt b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JUnitAssertToAssertJInspection.kt index 5f8bfe3..a7121a5 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JUnitAssertToAssertJInspection.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/inspections/JUnitAssertToAssertJInspection.kt @@ -29,90 +29,120 @@ class JUnitAssertToAssertJInspection : AbstractJUnitAssertInspection() { Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_TRUE_METHOD).parameterTypes(JAVA_LANG_STRING, BOOLEAN), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_TRUE_METHOD).parameterTypes(BOOLEAN, JAVA_LANG_STRING), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_TRUE_METHOD).parameterTypes(BOOLEAN), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_TRUE_METHOD).parameterTypes(BOOLEAN), ), MethodNames.IS_TRUE, hasExpected = false ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_FALSE_METHOD).parameterTypes(JAVA_LANG_STRING, BOOLEAN), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_FALSE_METHOD).parameterTypes(BOOLEAN, JAVA_LANG_STRING), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_FALSE_METHOD).parameterTypes(BOOLEAN), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_FALSE_METHOD).parameterTypes(BOOLEAN), ), MethodNames.IS_FALSE, hasExpected = false ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NULL_METHOD).parameterTypes(JAVA_LANG_STRING, JAVA_LANG_OBJECT), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NULL_METHOD).parameterTypes(JAVA_LANG_OBJECT, JAVA_LANG_STRING), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NULL_METHOD).parameterTypes(JAVA_LANG_OBJECT), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NULL_METHOD).parameterTypes(JAVA_LANG_OBJECT), ), MethodNames.IS_NULL, hasExpected = false ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NOT_NULL_METHOD).parameterTypes(JAVA_LANG_STRING, JAVA_LANG_OBJECT), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NOT_NULL_METHOD).parameterTypes(JAVA_LANG_OBJECT, JAVA_LANG_STRING), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NOT_NULL_METHOD).parameterTypes(JAVA_LANG_OBJECT), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NOT_NULL_METHOD).parameterTypes(JAVA_LANG_OBJECT), ), MethodNames.IS_NOT_NULL, hasExpected = false ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(JAVA_LANG_STRING, DOUBLE, DOUBLE, DOUBLE), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(DOUBLE, DOUBLE, DOUBLE, JAVA_LANG_STRING), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(DOUBLE, DOUBLE, DOUBLE), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(DOUBLE, DOUBLE, DOUBLE), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(JAVA_LANG_STRING, FLOAT, FLOAT, FLOAT), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(FLOAT, FLOAT, FLOAT, JAVA_LANG_STRING), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(FLOAT, FLOAT, FLOAT), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterTypes(FLOAT, FLOAT, FLOAT), ), MethodNames.IS_CLOSE_TO, hasDelta = true ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterCount(3), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterCount(3), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterCount(2), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_EQUALS_METHOD).parameterCount(2), ), MethodNames.IS_EQUAL_TO ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(JAVA_LANG_STRING, DOUBLE, DOUBLE, DOUBLE), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(DOUBLE, DOUBLE, DOUBLE, JAVA_LANG_STRING), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(DOUBLE, DOUBLE, DOUBLE), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(DOUBLE, DOUBLE, DOUBLE), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(JAVA_LANG_STRING, FLOAT, FLOAT, FLOAT), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(FLOAT, FLOAT, FLOAT, JAVA_LANG_STRING), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(FLOAT, FLOAT, FLOAT), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterTypes(FLOAT, FLOAT, FLOAT), ), MethodNames.IS_NOT_CLOSE_TO, hasDelta = true ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterCount(3), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterCount(3), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterCount(2), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NOT_EQUALS_METHOD).parameterCount(2), ), MethodNames.IS_NOT_EQUAL_TO ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_SAME_METHOD).parameterCount(3), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_SAME_METHOD).parameterCount(3), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_SAME_METHOD).parameterCount(2), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_SAME_METHOD).parameterCount(2), ), MethodNames.IS_SAME_AS ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NOT_SAME_METHOD).parameterCount(3), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NOT_SAME_METHOD).parameterCount(3), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_NOT_SAME_METHOD).parameterCount(2), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_NOT_SAME_METHOD).parameterCount(2), ), MethodNames.IS_NOT_SAME_AS ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(JAVA_LANG_STRING, DOUBLE_ARR, DOUBLE_ARR, DOUBLE), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(DOUBLE_ARR, DOUBLE_ARR, DOUBLE, JAVA_LANG_STRING), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(DOUBLE_ARR, DOUBLE_ARR, DOUBLE), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(DOUBLE_ARR, DOUBLE_ARR, DOUBLE), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(JAVA_LANG_STRING, FLOAT_ARR, FLOAT_ARR, FLOAT), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(FLOAT_ARR, FLOAT_ARR, FLOAT, JAVA_LANG_STRING), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(FLOAT_ARR, FLOAT_ARR, FLOAT), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterTypes(FLOAT_ARR, FLOAT_ARR, FLOAT), ), MethodNames.CONTAINS_EXACTLY, hasDelta = true ), Mapping( anyOf( staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterCount(2), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterCount(2), staticCall(JUNIT4_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterCount(3), + staticCall(JUNIT5_ASSERT_CLASSNAME, ASSERT_ARRAY_EQUALS_METHOD).parameterCount(3), ), MethodNames.CONTAINS_EXACTLY ) @@ -122,27 +152,34 @@ class JUnitAssertToAssertJInspection : AbstractJUnitAssertInspection() { Mapping( anyOf( staticCall(JUNIT4_ASSUME_CLASSNAME, ASSUME_TRUE_METHOD).parameterTypes(JAVA_LANG_STRING, BOOLEAN), + staticCall(JUNIT5_ASSUME_CLASSNAME, ASSUME_TRUE_METHOD).parameterTypes(BOOLEAN, JAVA_LANG_STRING), staticCall(JUNIT4_ASSUME_CLASSNAME, ASSUME_TRUE_METHOD).parameterTypes(BOOLEAN), + staticCall(JUNIT5_ASSUME_CLASSNAME, ASSUME_TRUE_METHOD).parameterTypes(BOOLEAN), ), MethodNames.IS_TRUE, hasExpected = false ), Mapping( anyOf( staticCall(JUNIT4_ASSUME_CLASSNAME, ASSUME_FALSE_METHOD).parameterTypes(JAVA_LANG_STRING, BOOLEAN), + staticCall(JUNIT5_ASSUME_CLASSNAME, ASSUME_FALSE_METHOD).parameterTypes(BOOLEAN, JAVA_LANG_STRING), staticCall(JUNIT4_ASSUME_CLASSNAME, ASSUME_FALSE_METHOD).parameterTypes(BOOLEAN), + staticCall(JUNIT5_ASSUME_CLASSNAME, ASSUME_FALSE_METHOD).parameterTypes(BOOLEAN), ), MethodNames.IS_FALSE, hasExpected = false ), Mapping( anyOf( staticCall(JUNIT4_ASSUME_CLASSNAME, ASSUME_NOT_NULL_METHOD).parameterCount(1), + staticCall(JUNIT5_ASSUME_CLASSNAME, ASSUME_NOT_NULL_METHOD).parameterCount(1), ), MethodNames.IS_NOT_NULL, hasExpected = false, singleArgument = true ), Mapping( anyOf( staticCall(JUNIT4_ASSUME_CLASSNAME, ASSUME_NO_EXCEPTION).parameterTypes(JAVA_LANG_STRING, JAVA_LANG_THROWABLE), + staticCall(JUNIT5_ASSUME_CLASSNAME, ASSUME_NO_EXCEPTION).parameterTypes(JAVA_LANG_THROWABLE, JAVA_LANG_STRING), staticCall(JUNIT4_ASSUME_CLASSNAME, ASSUME_NO_EXCEPTION).parameterTypes(JAVA_LANG_THROWABLE), + staticCall(JUNIT5_ASSUME_CLASSNAME, ASSUME_NO_EXCEPTION).parameterTypes(JAVA_LANG_THROWABLE), ), "doesNotThrowAnyException", hasExpected = false ) @@ -156,35 +193,37 @@ class JUnitAssertToAssertJInspection : AbstractJUnitAssertInspection() { override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { super.visitMethodCallExpression(expression) when (expression.resolveMethod()?.containingClass?.qualifiedName) { - JUNIT4_ASSERT_CLASSNAME -> visitMethodCallExpressionAssert(holder, expression) - JUNIT4_ASSUME_CLASSNAME -> visitMethodCallExpressionAssume(holder, expression) + JUNIT4_ASSERT_CLASSNAME -> visitMethodCallExpressionAssert(holder, expression, false) + JUNIT5_ASSERT_CLASSNAME -> visitMethodCallExpressionAssert(holder, expression, true) + JUNIT4_ASSUME_CLASSNAME -> visitMethodCallExpressionAssume(holder, expression, false) + JUNIT5_ASSUME_CLASSNAME -> visitMethodCallExpressionAssume(holder, expression, true) } } } } - private fun visitMethodCallExpressionAssert(holder: ProblemsHolder, expression: PsiMethodCallExpression) { + private fun visitMethodCallExpressionAssert(holder: ProblemsHolder, expression: PsiMethodCallExpression, junit5: Boolean) { JavaPsiFacade.getInstance(expression.project) .findClass(AssertJClassNames.ASSERTIONS_CLASSNAME, GlobalSearchScope.allScope(expression.project)) ?: return val mapping = ASSERT_MAPPINGS.firstOrNull { it.callMatcher.test(expression) } ?: return if (mapping.hasDelta) { registerConvertMethod(holder, expression, mapping.replacement, MethodNames.ASSERT_THAT) { desc, method -> - ReplaceJUnitDeltaAssertMethodCallQuickFix(desc, method) + ReplaceJUnitDeltaAssertMethodCallQuickFix(desc, method, junit5) } } else { registerConvertMethod(holder, expression, mapping.replacement, MethodNames.ASSERT_THAT) { desc, method -> - ReplaceJUnitAssertMethodCallQuickFix(desc, method, !mapping.hasExpected) + ReplaceJUnitAssertMethodCallQuickFix(desc, method, !mapping.hasExpected, junit5) } } } - private fun visitMethodCallExpressionAssume(holder: ProblemsHolder, expression: PsiMethodCallExpression) { + private fun visitMethodCallExpressionAssume(holder: ProblemsHolder, expression: PsiMethodCallExpression, junit5: Boolean) { JavaPsiFacade.getInstance(expression.project) .findClass(AssertJClassNames.ASSUMPTIONS_CLASSNAME, GlobalSearchScope.allScope(expression.project)) ?: return val mapping = ASSUME_MAPPINGS.firstOrNull { it.callMatcher.test(expression) } ?: return if (!mapping.singleArgument || expression.argumentList.expressions.size == 1) { registerConvertMethod(holder, expression, mapping.replacement, MethodNames.ASSUME_THAT) { desc, method -> - ReplaceJUnitAssumeMethodCallQuickFix(desc, method) + ReplaceJUnitAssumeMethodCallQuickFix(desc, method, junit5) } } } diff --git a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitAssertMethodCallQuickFix.kt b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitAssertMethodCallQuickFix.kt index d9b99b8..17be884 100644 --- a/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitAssertMethodCallQuickFix.kt +++ b/src/main/java/de/platon42/intellij/plugins/cajon/quickfixes/ReplaceJUnitAssertMethodCallQuickFix.kt @@ -7,7 +7,7 @@ import com.intellij.psi.PsiMethodCallExpression import de.platon42.intellij.plugins.cajon.* import de.platon42.intellij.plugins.cajon.AssertJClassNames.Companion.GUAVA_ASSERTIONS_CLASSNAME -class ReplaceJUnitAssertMethodCallQuickFix(description: String, private val replacementMethod: String, private val noExpectedExpression: Boolean) : +class ReplaceJUnitAssertMethodCallQuickFix(description: String, private val replacementMethod: String, private val noExpectedExpression: Boolean, private val junit5: Boolean) : AbstractCommonQuickFix(description) { companion object { @@ -23,14 +23,20 @@ class ReplaceJUnitAssertMethodCallQuickFix(description: String, private val repl val methodCallExpression = element as? PsiMethodCallExpression ?: return val args = methodCallExpression.argumentList val count = args.expressions.size - val actualExpression = args.expressions[count - 1] ?: return - val (expectedExpressions, messageExpression) = if (noExpectedExpression) { - val message = args.expressions.getOrNull(count - 2) - emptyArray