During the execution of the rule, the obtained full name is "Test" rather than "org.junit.test"

The purpose of the rule is to prohibit the use of JUnit4. However, during the execution of the rule, the obtained full name is “Test” rather than “org.junit.test”, which leads to the failure of the rule’s operation.

However, when executing the rule in a normal environment, the rule runs correctly, which means that the error only occurs during testing.

rule code :slight_smile:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.check.Rule;
import org.sonar.plugins.java.api.JavaFileScanner;
import org.sonar.plugins.java.api.JavaFileScannerContext;
import org.sonar.plugins.java.api.tree.AnnotationTree;
import org.sonar.plugins.java.api.tree.BaseTreeVisitor;
import org.sonar.plugins.java.api.tree.IdentifierTree;
import org.sonar.plugins.java.api.tree.MethodTree;
import org.sonar.plugins.java.api.tree.Tree;
import org.sonar.plugins.java.api.tree.TypeTree;

import java.util.List;


@Rule(key = "JunitTestSupport")
public class JunitTestSupportRule extends BaseTreeVisitor implements JavaFileScanner {

    private static final Logger LOG = LoggerFactory.getLogger(JunitTestSupportRule.class);

    public static final String TEST_NAME = "Test";

    private JavaFileScannerContext context;

    @Override
    public void scanFile(JavaFileScannerContext context) {
        this.context = context;
        scan(context.getTree());
    }

    @Override
    public void visitMethod(MethodTree tree) {
        LOG.debug("JunitTestSupportRule visitMethod,tree ={}",tree.symbol().signature());
        List<AnnotationTree> annotations = tree.modifiers().annotations();
        for (AnnotationTree annotationTree : annotations) {
            TypeTree annotationType = annotationTree.annotationType();
            if (annotationType.is(Tree.Kind.IDENTIFIER)) {
                IdentifierTree identifier = (IdentifierTree) annotationType;
                if (isJunit4TestMethod(tree) && identifier.name().equals(TEST_NAME)) {
                    context.reportIssue(this, identifier, "新测试用例框架不支持junit4");
                }
            }
        }
        super.visitMethod(tree);
    }

    private static boolean isJunit4TestMethod(MethodTree tree) {
        return tree.symbol()
                .metadata()
                .isAnnotatedWith("org.junit.Test");
    }
}

test file :slight_smile:

import org.junit.Test;


public class JunitTestSupportRuleTest{
    @Test
    public void testSuccess() {
        Assert.assertEquals("0", "0");
    }
}

Hi,

Welcome to the community!

What version of SonarQube are you working against?

 
Thx,
Ann

sonarqube-10.4.1.88267

<sonar.plugin.api.version>9.14.0.375</sonar.plugin.api.version>
<sonarjava.version>7.28.0.33738</sonarjava.version>

Hey there, thanks for reaching out.

However, when executing the rule in a normal environment, the rule runs correctly, which means that the error only occurs during testing.

Can you elaborate more on what is a “normal environment”?

I think that in the non-working case, there is some missing semantic information about the annotation package. Maybe you did not compile your test sources before running your unit tests?

Without the compiled files in the classpath, the AST generated will miss semantic information and you will not have the fully qualified name of some classes/methods.

this is the same issue as this post: Local run on AssertionsInTestsCheckTest.java failed - SonarQube / Plugin Development - Sonar Community (sonarsource.com), All the annotation in junit test will ignore the imports.

normal environment means after the plugins are installed, both mvn and SonarLint can be executed normally.

@ Leonardo Pilastri:
Any suggested fix to this then? thanks

Have you tried upgrading the sonar-java plugin version that you rely on? In the repository you shared I see in the root pom.xml file that the <sonar.java.version> is set to 7.30.0.34429 which is quite old, and I think the issue that you have is related to the classpath being empty in the InternalCheckVerifier that comes from that version, which used a different way of loading the classpath.

Please update to some later sonar-java released version and let me know if the behavior changes

Just tried again with updated sources from sonar-java-7.34.0.35958, issues are the same. Issues might not be related to sonar-java version.

Github Repo: ct24p/java-custom-rules-example: sonar-java example (github.com)
Reported issues:

this post itself [ During the execution of the rule, the obtained full name is “Test” rather than “org.junit.test” - SonarQube / Writing rules - Sonar Community (sonarsource.com)] &

Local run on AssertionsInTestsCheckTest.java failed - SonarQube / Plugin Development - Sonar Community (sonarsource.com)

I think the issue is related to the classpath provided to the CheckVerifier.

Are you using the CheckVerifier like this?

CheckVerifier.newVerifier()
      .onFile("src/test/files/SpringControllerRequestMappingEntityRule.java")
      .withCheck(new SpringControllerRequestMappingEntityRule())
      .withClassPath(FilesUtils.getClassPath("target/test-jars"))
      .verifyIssues();

Using the withClassPath(FilesUtils.getClassPath("target/test-jars")) will provide the analysis with the knowledge of all dependencies defined in the pom.xml under:

<!-- only required to run UT - these are UT dependencies -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <id>copy</id>
            <phase>test-compile</phase>
            <goals>
              <goal>copy</goal>
            </goals>
            <configuration>
              <artifactItems>
               ...
               ...

@Leonardo_Pilastri : Thanks this fixed junt4 test, junit5 still failed.

Do you have both dependencies to junit4 and junit5 inside the maven-dependency-plugin?

junit-jupiter 5.10.2