junit 5: check static attribute according to TestInstance configured

This commit is contained in:
Anna.Kozlova
2017-11-20 10:07:36 +01:00
parent 56edc70ea1
commit 8e3c26b879
5 changed files with 53 additions and 7 deletions
@@ -21,5 +21,6 @@
<orderEntry type="library" exported="" name="ASM" level="project" />
<orderEntry type="library" name="StreamEx" level="project" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="module" module-name="openapi" />
</component>
</module>
@@ -16,6 +16,7 @@
package com.siyeh.ig.psiutils;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.MetaAnnotationUtil;
import com.intellij.codeInsight.TestFrameworks;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
@@ -25,12 +26,14 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.testIntegration.TestFramework;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.hash.HashSet;
import com.siyeh.ig.callMatcher.CallMatcher;
import com.siyeh.ig.junit.JUnitCommonClassNames;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Set;
import static com.intellij.codeInsight.AnnotationUtil.CHECK_HIERARCHY;
@@ -148,13 +151,23 @@ public class TestUtils {
* @return true if class is annotated with {@code @TestInstance(TestInstance.Lifecycle.PER_CLASS)}
*/
public static boolean testInstancePerClass(@NotNull PsiClass containingClass) {
PsiAnnotation annotation = AnnotationUtil.findAnnotation(containingClass, JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_TEST_INSTANCE);
return testInstancePerClass(containingClass, new HashSet<>());
}
private static boolean testInstancePerClass(@NotNull PsiClass containingClass, HashSet<PsiClass> classes) {
PsiAnnotation annotation = MetaAnnotationUtil.findMetaAnnotations(containingClass, Collections.singletonList(JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_TEST_INSTANCE))
.findFirst().orElse(null);
if (annotation != null) {
PsiAnnotationMemberValue value = annotation.findDeclaredAttributeValue(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
if (value != null && value.getText().contains("PER_CLASS")) {
return true;
}
}
else {
for (PsiClass superClass : containingClass.getSupers()) {
if (classes.add(superClass) && testInstancePerClass(superClass, classes)) return true;
}
}
return false;
}
@@ -28,6 +28,7 @@ import com.intellij.psi.util.TypeConversionUtil
import com.intellij.util.containers.ContainerUtil
import com.siyeh.InspectionGadgetsBundle
import com.siyeh.ig.junit.JUnitCommonClassNames
import com.siyeh.ig.psiutils.TestUtils
import org.jetbrains.annotations.Nls
import java.util.*
@@ -154,14 +155,16 @@ class JUnit5MalformedParameterizedInspection : AbstractBaseJavaLocalInspectionTo
processArrayInAnnotationParameter(annotationMemberValue, { attributeValue ->
for (reference in attributeValue.references) {
if (reference is MethodSourceReference) {
val containingClass = method.containingClass
val resolve = reference.resolve()
if (resolve !is PsiMethod) {
val containingClass = method.containingClass
var createFix : CreateMethodQuickFix? = null
if (containingClass != null && holder.isOnTheFly)
if (containingClass != null && holder.isOnTheFly) {
val staticModifier = if (!TestUtils.testInstancePerClass(containingClass)) " static" else "";
createFix = CreateMethodQuickFix.createFix(containingClass,
"static Object[][] " + reference.value + "()",
"private$staticModifier Object[][] " + reference.value + "()",
"return new Object[][] {};")
}
holder.registerProblem(attributeValue,
"Cannot resolve target method source: \'" + reference.value + "\'",
createFix)
@@ -170,7 +173,8 @@ class JUnit5MalformedParameterizedInspection : AbstractBaseJavaLocalInspectionTo
val sourceProvider : PsiMethod = resolve
val providerName = sourceProvider.name
if (!sourceProvider.hasModifierProperty(PsiModifier.STATIC)) {
if (!sourceProvider.hasModifierProperty(PsiModifier.STATIC) &&
containingClass != null && !TestUtils.testInstancePerClass(containingClass)) {
holder.registerProblem(attributeValue, "Method source \'$providerName\' must be static",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
QuickFixFactory.getInstance().createModifierListFix(sourceProvider, PsiModifier.STATIC, true, false))
@@ -248,12 +252,12 @@ class JUnit5MalformedParameterizedInspection : AbstractBaseJavaLocalInspectionTo
if (InheritanceUtil.isInheritor(returnType, CommonClassNames.JAVA_UTIL_STREAM_LONG_STREAM)) return PsiType.LONG
if (InheritanceUtil.isInheritor(returnType, CommonClassNames.JAVA_UTIL_STREAM_DOUBLE_STREAM)) return PsiType.DOUBLE
val streamItemType = PsiUtil.substituteTypeParameter(returnType, CommonClassNames.JAVA_UTIL_STREAM_STREAM, 0, false)
val streamItemType = PsiUtil.substituteTypeParameter(returnType, CommonClassNames.JAVA_UTIL_STREAM_STREAM, 0, true)
if (streamItemType != null) {
return streamItemType
}
return PsiUtil.substituteTypeParameter(returnType, CommonClassNames.JAVA_UTIL_ITERATOR, 0, false)
return PsiUtil.substituteTypeParameter(returnType, CommonClassNames.JAVA_UTIL_ITERATOR, 0, true)
}
}
}
@@ -66,12 +66,18 @@ public class JUnit5MalformedParameterizedTest extends LightInspectionTestCase {
addEnvironmentClass("package org.junit.jupiter.params.provider;\n" +
"public @interface ArgumentsSource {}");
addEnvironmentClass("package org.junit.jupiter.api;\n" +
"public @interface TestInstance {\n" +
"enum Lifecycle {PER_CLASS, PER_METHOD;}\n" +
"Lifecycle value();}");
}
public void testMalformedSources() { doTest(); }
public void testMethodSource() { doTest(); }
public void testMalformedSourcesImplicitConversion() { doTest(); }
public void testMalformedSourcesImplicitParameters() { doTest(); }
public void testMalformedSourcesTestInstancePerClass() { doTest(); }
@Override
protected String getBasePath() {
@@ -0,0 +1,22 @@
import java.util.Arrays;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.api.TestInstance;
@TestInstance( TestInstance.Lifecycle.PER_CLASS )
@interface Meta{}
@Meta
abstract class AbstractTest {}
class TestWithMethodSource extends AbstractTest {
@ParameterizedTest
@MethodSource("getParameters")
public void shouldExecuteWithParameterizedMethodSource(String arguments) { }
public Stream getParameters(){ //non static but that's expected due to PER_CLASS test instance
return Arrays.asList( "Another execution", "Last execution").stream();
}
}