java - JUnit5-木星 : Composed ( ="meta") annotation does not resolve to annotation definition

标签 java reflection annotations junit5 junit-jupiter

我定义了自己的 JUnit 注释:

@ParameterizedTest
@MethodSource("myorg.qa.ccrtesting.DataProviders#standardDataProvider")
@Tags({@Tag("ccr"), @Tag("standard")})
public @interface CcrStandardTest {
}

然后,我可以在测试中使用该注释:

@CcrStandardTest
public void E0010_contact_standard (String testData) {
...
  • 我的运行配置:
    JVM 选项:-ea
    类:myorg.qa.ccrtesting.ccrstandardtests.CcrStanConTest - 这是 IDE 建议的(并经过验证指向正确的类,其中包含我的原型(prototype)测试方法)

但是,这会导致:jupiter.api.extension.ParameterResolutionException:在方法 [public void... 中没有为参数 [java.lang.String arg0] 注册 ParameterResolver。

  • 我尝试从测试方法签名中删除 String testData,但 JUnit 没有执行任何测试:未找到测试

  • 当我在原型(prototype)测试方法上方添加 @Test 时,它会执行但是:

    1. 似乎我在 @CcrStandardTest 下定义的注释均未应用
    2. IDE 建议可疑的组合 @Test 和参数化源
      (我已经知道 @ParameterizedTest 暗示 @Test,只是不确定为什么 IDE 能够找到自定义注释,而 JUnit 却不能?)

最佳答案

正如您所发现的,您需要将 @Retention(RUNTIME) 添加到您的组合注释中,以便 JUnit 能够看到它。 Java 中的注释具有三种不同的保留策略:

  • RetentionPolicy.SOURCE

    Annotations are to be discarded by the compiler.

  • RetentionPolicy.CLASS

    Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time. This is the default behavior. [emphasis added]

  • RetentionPolicy.RUNTIME

    Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.

正如我上面强调的,如果您没有显式添加 @Retention(...),则使用 CLASS 策略。这不适用于 JUnit,因为 JUnit 不会扫描 *.class 文件(即字节码)中的注释,它会反射性地扫描加载的类来查找测试方法。如果没有 RUNTIME 保留策略,您的注释将无法通过反射方式访问,因此 JUnit 永远不会看到它,因此不会执行测试。

@Target注释:

Indicates the contexts in which an annotation type is applicable. The declaration contexts and type contexts in which an annotation type may be applicable are specified in JLS 9.6.4.1, and denoted in source code by enum constants of java.lang.annotation.ElementType.

If an @Target meta-annotation is not present on an annotation type T , then an annotation of type T may be written as a modifier for any declaration except a type parameter declaration.

If an @Target meta-annotation is present, the compiler will enforce the usage restrictions indicated by ElementType enum constants, in line with JLS 9.7.4.

在我对 your other question 的回答中,我使用了:

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

因为这与 @ParameterizedTest 使用的目标相同。我认为将其限制为 METHOD 是一个好主意,因为 @ParameterizedTest 的设计者显然认为只有方法应该由参数化测试扩展直接扩展(请参阅 §5 Extension Model )。包含 ANNOTATION_TYPE 允许您将组合注释放在另一个注释上,从而创建另一个组合注释。

您还会看到我包含了 @Documented :

If the annotation @Documented is present on the declaration of an annotation type A, then any @A annotation on an element is considered part of the element's public contract. In more detail, when an annotation type A is annotated with Documented, the presence and value of annotations of type A are a part of the public contract of the elements A annotates. Conversely, if an annotation type B is not annotated with Documented, the presence and value of B annotations are not part of the public contract of the elements B annotates. Concretely, if an annotation type is annotated with Documented, by default a tool like javadoc will display annotations of that type in its output while annotations of annotation types without Documented will not be displayed.

请注意,这些注释 - @Retention@Target@Documented - 并非特定于 JUnit。这些注释对于 Java 中注释的工作方式至关重要,每个注释都位于 java.lang.annotation 包中。

关于java - JUnit5-木星 : Composed ( ="meta") annotation does not resolve to annotation definition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60339277/

相关文章:

ios - 删除 Apple Maps 默认注释

swift - 删除包含等于/不等于字符串的标题的注释?

java - Tomcat 文件夹作为类路径?

java - 如何在关闭应用程序之前停止纹理 View 监听器并显示图像

java - Maven 全新安装构建失败 : Spring Boot- MVC, JPA

java - 将参数作为要调用的对象传递

java - 如何在输入文本时启用按钮并在 Android java 中禁用?

c# - 通过 Emit(Opcodes.Call, methodinfo) 创建一个类型的实例

c# - 项目之间的 Type.GetType() 可见性问题 (Visual C#)

annotations - 使用两个箭头将椭圆注释链接到方程的两项