JUnit5-Jupiter:组合 (="meta") 注释未解析为注释定义

JUnit5-Jupiter: Composed (="meta") annotation does not resolve to annotation definition

我定义了自己的 JUnit 注解:

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

然后,我能够在我的测试中使用该注释:

@CcrStandardTest
public void E0010_contact_standard (String testData) {
...

但是,这会导致:jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [java.lang.String arg0] in method [public void...

经过一些调查,我发现通过添加:@Retention(RUNIME)(需要两次导入),元注释定义将被解析。

JUnit 文档实际上在他们的组合注释示例中展示了这一点 (@Retention)。
他们还显示 @Target 也与它一起使用。
- 但都不解释...

这个答案不是最高质量的,因为我不知道 @Retention@Target 做了什么,但我希望它能帮助和我遇到同样问题的人得到去。

如果有人详细说明,我将很乐意编辑此答案或接受他们的答案!

如您所见,您需要将 @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 文件(即字节码)以获取注释,它会反射地扫描 loaded 类寻找测试方法。如果没有 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.

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

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

因为这与 @ParameterizedTest. I figured it was a good idea to restrict it to METHOD since the designers of @ParameterizedTest apparently feel that only methods should be directly extended by the parameterized-tests extension (see §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 包中。