Skip to content

Commit 9211a18

Browse files
authored
Merge pull request #50941 from michalvavrik/feature/support-quarkus-test-meta-annotation
Support using `@QuarkusTest` in meta-annotations
2 parents 4224d5f + d35766a commit 9211a18

14 files changed

+247
-3
lines changed

docs/src/main/asciidoc/getting-started-testing.adoc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,36 @@ For `@QuarkusIntegrationTest` tests that result in launcher the application as a
16401640
This can be used by `QuarkusTestResourceLifecycleManager` that need to launch additional containers that the application will communicate with.
16411641
====
16421642

1643+
== Creating `@QuarkusTest` meta-annotation
1644+
1645+
The `@QuarkusTest` annotation can be grouped with other annotations by defining a custom meta-annotation.
1646+
For instance, you can bundle it with the `@Tag` annotation to automatically mark a group of tests like in the example below:
1647+
1648+
[source,java]
1649+
----
1650+
org.acme.test
1651+
1652+
import java.lang.annotation.Documented;
1653+
import java.lang.annotation.ElementType;
1654+
import java.lang.annotation.Inherited;
1655+
import java.lang.annotation.Retention;
1656+
import java.lang.annotation.RetentionPolicy;
1657+
import java.lang.annotation.Target;
1658+
1659+
import io.quarkus.test.junit.QuarkusTest;
1660+
import org.junit.jupiter.api.Tag;
1661+
1662+
@Target(ElementType.TYPE)
1663+
@Retention(RetentionPolicy.RUNTIME)
1664+
@Documented
1665+
@Inherited
1666+
@QuarkusTest
1667+
@Tag("security")
1668+
public @interface QuarkusSecurityTest { <1>
1669+
}
1670+
----
1671+
<1> The `@QuarkusSecurityTest` annotation can be used instead of the `@QuarkusTest` annotation.
1672+
16431673
== Testing Components
16441674

16451675
Quarkus provides the `QuarkusComponentTestExtension`, a JUnit extension to ease the testing of components and mocking of their dependencies.

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/TestsAsBeansProcessor.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.List;
66
import java.util.Optional;
77
import java.util.Set;
8+
import java.util.stream.Collectors;
89

910
import org.jboss.jandex.AnnotationInstance;
1011
import org.jboss.jandex.AnnotationTarget;
@@ -61,7 +62,11 @@ public void testClassBeans(List<TestClassBeanBuildItem> items, BuildProducer<Add
6162

6263
@BuildStep(onlyIf = IsTest.class)
6364
AnnotationsTransformerBuildItem vetoTestClassesNotMatchingTestProfile(Optional<TestProfileBuildItem> testProfile,
64-
CombinedIndexBuildItem index) {
65+
CombinedIndexBuildItem index, List<TestAnnotationBuildItem> testAnnotationBuildItems) {
66+
Set<String> additionalTestAnnotationNames = testAnnotationBuildItems.stream()
67+
.map(TestAnnotationBuildItem::getAnnotationClassName)
68+
.filter(a -> !a.equals(QUARKUS_TEST.toString()))
69+
.collect(Collectors.toSet());
6570
// Since we only need to register all test classes that belong to the "current" test profile
6671
// we need to veto other test classes during the build
6772
return new AnnotationsTransformerBuildItem(AnnotationTransformation
@@ -71,7 +76,8 @@ AnnotationsTransformerBuildItem vetoTestClassesNotMatchingTestProfile(Optional<T
7176
boolean veto = false;
7277
if (maybeTestClass.hasAnnotation(QUARKUS_TEST)
7378
|| maybeTestClass.hasAnnotation(QUARKUS_INTEGRATION_TEST)
74-
|| maybeTestClass.hasAnnotation(QUARKUS_MAIN_TEST)) {
79+
|| maybeTestClass.hasAnnotation(QUARKUS_MAIN_TEST)
80+
|| additionalTestAnnotationNames.stream().anyMatch(maybeTestClass::hasAnnotation)) {
7581
String testProfileClassName = testProfile.map(TestProfileBuildItem::getTestProfileClassName)
7682
.orElse(null);
7783
veto = !matchesProfile(maybeTestClass, testProfileClassName);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.quarkus.it.extension;
2+
3+
import jakarta.enterprise.context.ApplicationScoped;
4+
import jakarta.inject.Inject;
5+
6+
import org.junit.jupiter.api.Assertions;
7+
import org.junit.jupiter.api.Test;
8+
9+
public abstract class AbstractQuarkusTestMetaAnnotationTest {
10+
11+
@Inject
12+
MyTestBean bean;
13+
14+
@Test
15+
void testInjectedBean() {
16+
Assertions.assertEquals("foo", bean.foo());
17+
}
18+
19+
@ApplicationScoped
20+
public static class MyTestBean {
21+
22+
public String foo() {
23+
return "foo";
24+
}
25+
26+
}
27+
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.quarkus.it.extension;
2+
3+
@QuarkusTestExtensionMetaAnnotationL1
4+
public class QuarkusTestExtensionMetaAnnotationHierarchyDepth1Test extends AbstractQuarkusTestMetaAnnotationTest {
5+
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.quarkus.it.extension;
2+
3+
@QuarkusTestExtensionMetaAnnotationL2
4+
public class QuarkusTestExtensionMetaAnnotationHierarchyDepth2Test extends AbstractQuarkusTestMetaAnnotationTest {
5+
6+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.quarkus.it.extension;
2+
3+
import java.lang.annotation.Documented;
4+
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Inherited;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
import org.junit.jupiter.api.extension.ExtendWith;
11+
12+
import io.quarkus.test.junit.QuarkusTestExtension;
13+
14+
@Target(ElementType.TYPE)
15+
@Retention(RetentionPolicy.RUNTIME)
16+
@Documented
17+
@Inherited
18+
@ExtendWith(QuarkusTestExtension.class)
19+
public @interface QuarkusTestExtensionMetaAnnotationL1 {
20+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package io.quarkus.it.extension;
2+
3+
import java.lang.annotation.Documented;
4+
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Inherited;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
@Target(ElementType.TYPE)
11+
@Retention(RetentionPolicy.RUNTIME)
12+
@Documented
13+
@Inherited
14+
@QuarkusTestExtensionMetaAnnotationL2Parent
15+
public @interface QuarkusTestExtensionMetaAnnotationL2 {
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.quarkus.it.extension;
2+
3+
import java.lang.annotation.Documented;
4+
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Inherited;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
import org.junit.jupiter.api.extension.ExtendWith;
11+
12+
import io.quarkus.test.junit.QuarkusTestExtension;
13+
14+
@Target(ElementType.TYPE)
15+
@Retention(RetentionPolicy.RUNTIME)
16+
@Documented
17+
@Inherited
18+
@ExtendWith(QuarkusTestExtension.class)
19+
public @interface QuarkusTestExtensionMetaAnnotationL2Parent {
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.quarkus.it.extension;
2+
3+
@QuarkusTestMetaAnnotationL1
4+
public class QuarkusTestMetaAnnotationHierarchyDepth1Test extends AbstractQuarkusTestMetaAnnotationTest {
5+
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.quarkus.it.extension;
2+
3+
@QuarkusTestMetaAnnotationL2
4+
public class QuarkusTestMetaAnnotationHierarchyDepth2Test extends AbstractQuarkusTestMetaAnnotationTest {
5+
6+
}

0 commit comments

Comments
 (0)