JUnit5-Jupiter: составная (= "мета") аннотация не преобразуется в определение аннотации - PullRequest
0 голосов
/ 21 февраля 2020

Я определил свою собственную аннотацию 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 - нет?)

Ответы [ 2 ]

1 голос
/ 21 февраля 2020

Как вы обнаружили, вам нужно добавить @Retention(RUNTIME) к вашей составной аннотации, чтобы JUnit мог ее увидеть. Аннотации в Java имеют три разные политики хранения:

  • RetentionPolicy.SOURCE

    Аннотации должны отбрасываться компилятором.

  • RetentionPolicy.CLASS

    Аннотации должны быть записаны в файле классов компилятором, но их не нужно сохранять ВМ во время выполнения. Это поведение по умолчанию. [выделение добавлено]

  • RetentionPolicy.RUNTIME

    Аннотации должны быть записаны в файле класса компилятором и сохранены виртуальной машиной во время выполнения, чтобы их можно было читать рефлексивно.

Как я Выделено выше, если вы явно не добавляете @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 на элементе считается частью открытого элемента c контракта элемента. Более подробно, когда тип аннотации A помечен Documented, наличие и значение аннотаций типа A являются частью публикации c Контракт элементов A комментирует. И наоборот, если тип аннотации B не аннотирован Documented, наличие и значение аннотаций B не являются частью договора c на публикацию элементы B комментирует. Конкретно, если аннотированный тип аннотации Documented, по умолчанию такой инструмент, как javado c, будет отображать аннотации этого типа в своем выводе, в то время как аннотации типов аннотации без Documented не будут отображаться.

Обратите внимание, что эти аннотации - @Retention, @Target и @Documented - не указывают c для JUnit. Эти аннотации имеют основополагающее значение для работы аннотаций в Java, и каждая из них находится в пакете java.lang.annotation.

0 голосов
/ 21 февраля 2020

После некоторых исследований я обнаружил, что, добавив: @Retention(RUNIME) (потребуется два импорта), определение метааннотации будет разрешено.

Документы JUnit действительно показывают это (@Retention) в своем примере составных аннотаций.
Они также показывают, что @Target также используется с ним.
- Но не объясните ни того, ни другого ...

Этот ответ не самого высокого качества, так как я этого не делаю знаю, что делают @Retention и @Target, но я надеюсь, что это поможет любому, кто застрял с той же проблемой, что и я, приступить к работе.

Если кто-то уточнит, я буду рад отредактировать этот ответ или принять его !

...