0

我定义了自己的 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 建议的(并已验证指向正确的类,该类包含我的原型测试方法)

但是,这会导致: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
      (我已经知道@ParameterizedTest暗示@Test,只是不确定为什么 IDE 能够找到自定义注释但 JUnit 不是?)
4

2 回答 2

1

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

  • RetentionPolicy.SOURCE

    注释将被编译器丢弃。

  • RetentionPolicy.CLASS

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

  • RetentionPolicy.RUNTIME

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

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

@Target注释:

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

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

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

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

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

因为这与@ParameterizedTest. 我认为将其限制为一个好主意,METHOD因为设计人员@ParameterizedTest显然认为只有方法应该由参数化测试扩展直接扩展(参见§5 扩展模型)。并且包括ANNOTATION_TYPE允许您将组合注释放在另一个注释上,从而创建另一个组合注释。

你还会看到我包括@Documented

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

请注意,这些注释——<code>@Retention、@Target@Documented——并不特定于 JUnit。这些注解是 Java 中注解如何工作的基础,每一个都驻留在java.lang.annotation包中。

于 2020-02-21T14:17:50.427 回答
0

经过一番调查,我发现通过添加:(@Retention(RUNIME)需要两个导入),元注释定义将得到解决。

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

这个答案不是最高质量的,因为我不知道做什么@Retention@Target做什么,但我希望它能帮助任何与我遇到同样问题的人继续前进。

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

于 2020-02-21T13:20:48.267 回答