JUnit5-Jupiter:组合(=“元”)注释无法解析为注释定义

Dra*_*max 2 java reflection annotations junit5 junit-jupiter

我定义了自己的 JUnit 注释:

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

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

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

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

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

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

    1. 似乎我定义的注释都没有@CcrStandardTest被应用
    2. IDE 建议suspicious combination @Test and parameterized source
      (我已经知道@ParameterizedTestimply @Test,只是不确定为什么 IDE 能够找到自定义注释,而 JUnit 却不能?)

Sla*_*law 5

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

\n\n
    \n
  • RetentionPolicy.SOURCE

    \n\n
    \n

    注释将被编译器丢弃。

    \n
  • \n
  • RetentionPolicy.CLASS

    \n\n
    \n

    注释将由编译器记录在类文件中,但不需要在运行时由 VM 保留。这是默认行为。 [强调]

    \n
  • \n
  • RetentionPolicy.RUNTIME

    \n\n
    \n

    注解将由编译器记录在类文件中,并在运行时由VM保留,因此可以反射性地读取它们。

    \n
  • \n
\n\n

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

\n\n

注释@Target

\n\n
\n

指示注释类型适用的上下文。注释类型可能适用的声明上下文和类型上下文在 JLS 9.6.4.1 中指定,并在源代码中由 的枚举常量表示java.lang.annotation.ElementType

\n\n

如果@Target注释类型上不存在元注释T,则类型注释T可以被编写为除类型参数声明之外的任何声明的修饰符。

\n\n

如果@Target存在元注释,编译器将强制执行ElementType枚举常量指示的使用限制,与 JLS 9.7.4 一致。

\n
\n\n

在我对你的另一个问题的回答中,我使用了:

\n\n
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})\n
Run Code Online (Sandbox Code Playgroud)\n\n

因为这与@ParameterizedTest. 我认为限制它是一个好主意,METHOD因为设计者@ParameterizedTest显然认为只有方法应该通过参数化测试扩展直接扩展(参见\xc2\xa75 扩展模型)。包含ANNOTATION_TYPE允许您将组合注释放置在另一个注释上,从而创建另一个组合注释。

\n\n

您还会看到我包括@Documented

\n\n
\n

如果注释@Documented出现在注释类型的声明中A,则@A元素上的任何注释都被视为该元素的公共契约的一部分。更详细地说,当注释类型A用 注释时Documented,类型注释的存在和值A是元素注释的公共契约的一部分A。相反,如果注释类型B未使用 进行注释Documented,则注释的存在和值B不属于所B注释元素的公共契约的一部分。具体来说,如果注释类型带有 注释Documented,默认情况下,像 javadoc 这样的工具将在其输出中显示该类型的注释,而没有注释类型的注释Documented将不会显示。

\n
\n\n

请注意,这些注释 \xe2\x80\x94 @Retention@Target@Documented\xe2\x80\x94 并非特定于 JUnit。这些注释对于 Java 中注释的工作方式至关重要,并且每个注释都驻留在java.lang.annotation包中。

\n