OWB-1286 first JUnit 5 integration
git-svn-id: https://svn.apache.org/repos/asf/openwebbeans/trunk@1858345 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index 18d02ac..051fed1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -379,7 +379,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
- <version>2.19.1</version>
+ <version>3.0.0-M3</version>
<configuration>
<includes>
<include>**/*Test.java</include>
@@ -557,6 +557,7 @@
<module>webbeans-maven</module>
<module>webbeans-gradle</module>
<module>webbeans-se</module>
+ <module>webbeans-junit5</module>
</modules>
<dependencyManagement>
diff --git a/webbeans-junit5/pom.xml b/webbeans-junit5/pom.xml
new file mode 100644
index 0000000..685f231
--- /dev/null
+++ b/webbeans-junit5/pom.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.openwebbeans</groupId>
+ <artifactId>openwebbeans</artifactId>
+ <version>2.0.11-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>openwebbeans-junit5</artifactId>
+ <name>OpenWebBeans JUnit5</name>
+ <description>
+ Apache OpenWebBeans JUnit 5 integration
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-annotation_1.3_spec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jcdi_2.0_spec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-atinject_1.0_spec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-interceptor_1.2_spec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.openwebbeans</groupId>
+ <artifactId>openwebbeans-se</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <version>5.4.2</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-test</id>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </execution>
+ <execution>
+ <id>perclass</id>
+ <phase>test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <includes>**/perclass/*</includes>
+ </configuration>
+ </execution>
+ <execution>
+ <id>reusable</id>
+ <phase>test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <includes>**/reusable/*</includes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/Cdi.java b/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/Cdi.java
new file mode 100644
index 0000000..f6c07a8
--- /dev/null
+++ b/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/Cdi.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openwebbeans.junit5;
+
+import org.apache.openwebbeans.junit5.internal.CdiExtension;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.io.Closeable;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.function.Supplier;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Activates CDI based on SE API for the decorated test.
+ *
+ * IMPORTANT: this is not thread safe - yet - so ensure to use a single fork in surefire/gradle/....
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@ExtendWith(CdiExtension.class)
+public @interface Cdi
+{
+ /**
+ * @return classes to deploy.
+ */
+ Class<?>[] classes() default {};
+
+ /**
+ * @return decorators to activate.
+ */
+ Class<?>[] decorators() default {};
+
+ /**
+ * @return interceptors to activate.
+ */
+ Class<?>[] interceptors() default {};
+
+ /**
+ * @return alternatives to activate.
+ */
+ Class<?>[] alternatives() default {};
+
+ /**
+ * @return stereotypes to activate.
+ */
+ Class<? extends Annotation>[] alternativeStereotypes() default {};
+
+ /**
+ * @return packages to deploy.
+ */
+ Class<?>[] packages() default {};
+
+ /**
+ * @return packages to deploy recursively.
+ */
+ Class<?>[] recursivePackages() default {};
+
+ /**
+ * @return if the automatic scanning must be disabled.
+ */
+ boolean disableDiscovery() default false;
+
+ /**
+ * @return an array of callback to call before the container starts.
+ */
+ Class<? extends OnStart>[] onStarts() default {};
+
+ /**
+ * TIP: it is recommended to alias the configuration when this is true to avoid to have a not unified configuration.
+ * IMPORTANT: this is not thread safe so ensure to use a single fork when using it.
+ *
+ * @return true if the underlying container must stay up until the end of the tests.
+ */
+ boolean reusable() default false;
+
+ /**
+ * Will be execute before the container starts and can return a closeable called after the container stops.
+ */
+ interface OnStart extends Supplier<Closeable>
+ {
+ }
+}
diff --git a/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/internal/CdiExtension.java b/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/internal/CdiExtension.java
new file mode 100644
index 0000000..1c97389
--- /dev/null
+++ b/webbeans-junit5/src/main/java/org/apache/openwebbeans/junit5/internal/CdiExtension.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openwebbeans.junit5.internal;
+
+import org.apache.openwebbeans.junit5.Cdi;
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.platform.commons.util.AnnotationUtils;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.se.SeContainer;
+import javax.enterprise.inject.se.SeContainerInitializer;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionTarget;
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Objects;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+// todo: enhance the setup to be thread safe? see Meecrowave ClassLoaderLock class and friends
+public class CdiExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback
+{
+ private static SeContainer reusableContainer;
+
+ private SeContainer container;
+ private CreationalContext<Object> creationalContext;
+ private Closeable[] onStop;
+
+ @Override
+ public void beforeAll(final ExtensionContext extensionContext)
+ {
+ final Cdi config = AnnotationUtils.findAnnotation(extensionContext.getElement(), Cdi.class).orElse(null);
+ if (config == null)
+ {
+ return;
+ }
+
+ final boolean reusable = config.reusable();
+ if (reusable && reusableContainer != null)
+ {
+ return;
+ }
+ if (!reusable && reusableContainer != null)
+ {
+ throw new IllegalStateException(
+ "You can't mix @Cdi(reusable=true) and @Cdi(reusable=false) in the same suite");
+ }
+
+ final SeContainerInitializer initializer = SeContainerInitializer.newInstance();
+ if (config.disableDiscovery())
+ {
+ initializer.disableDiscovery();
+ }
+ initializer.setClassLoader(Thread.currentThread().getContextClassLoader());
+ initializer.addBeanClasses(config.classes());
+ initializer.enableDecorators(config.decorators());
+ initializer.enableInterceptors(config.interceptors());
+ initializer.selectAlternatives(config.alternatives());
+ initializer.selectAlternativeStereotypes(config.alternativeStereotypes());
+ initializer.addPackages(
+ Stream.of(config.packages()).map(Class::getPackage).toArray(Package[]::new));
+ initializer.addPackages(true,
+ Stream.of(config.recursivePackages()).map(Class::getPackage).toArray(Package[]::new));
+ onStop = Stream.of(config.onStarts())
+ .map(it ->
+ {
+ try
+ {
+ return it.getConstructor().newInstance();
+ }
+ catch (final InstantiationException | IllegalAccessException | NoSuchMethodException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ catch (final InvocationTargetException e)
+ {
+ throw new IllegalStateException(e.getTargetException());
+ }
+ })
+ .peek(Supplier::get)
+ .filter(Objects::nonNull)
+ .toArray(Closeable[]::new);
+ if (reusable)
+ {
+ reusableContainer = initializer.initialize();
+ Runtime.getRuntime().addShutdownHook(new Thread(
+ () -> doClose(reusableContainer), getClass().getName() + "-shutdown"));
+ }
+ else
+ {
+ container = initializer.initialize();
+ }
+ }
+
+ @Override
+ public void afterAll(final ExtensionContext extensionContext)
+ {
+ if (container != null)
+ {
+ doClose(container);
+ container = null;
+ }
+ }
+
+ @Override
+ public void beforeEach(final ExtensionContext extensionContext)
+ {
+ if (container == null && reusableContainer == null)
+ {
+ return;
+ }
+ extensionContext.getTestInstance().ifPresent(instance ->
+ {
+ final BeanManager manager = (container == null ? reusableContainer : container).getBeanManager();
+ final AnnotatedType<?> annotatedType = manager.createAnnotatedType(instance.getClass());
+ final InjectionTarget injectionTarget = manager.createInjectionTarget(annotatedType);
+ creationalContext = manager.createCreationalContext(null);
+ injectionTarget.inject(instance, creationalContext);
+ });
+ }
+
+ @Override
+ public void afterEach(final ExtensionContext extensionContext)
+ {
+ if (creationalContext != null)
+ {
+ creationalContext.release();
+ creationalContext = null;
+ }
+ }
+
+ private void doClose(final SeContainer container)
+ {
+ container.close();
+ Stream.of(onStop).forEach(it ->
+ {
+ try
+ {
+ it.close();
+ }
+ catch (final IOException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ });
+ }
+}
diff --git a/webbeans-junit5/src/main/resources/META-INF/beans.xml b/webbeans-junit5/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..fd08856
--- /dev/null
+++ b/webbeans-junit5/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<beans version="2.0" bean-discovery-mode="none" />
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/bean/MyService.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/bean/MyService.java
new file mode 100644
index 0000000..2fc35a1
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/bean/MyService.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openwebbeans.junit5.bean;
+
+import javax.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class MyService {
+ public String ok() {
+ return "ok";
+ }
+}
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/perclass/CdiTest.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/perclass/CdiTest.java
new file mode 100644
index 0000000..07e2a0c
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/perclass/CdiTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openwebbeans.junit5.perclass;
+
+import org.apache.openwebbeans.junit5.Cdi;
+import org.apache.openwebbeans.junit5.bean.MyService;
+import org.junit.jupiter.api.Test;
+
+import javax.inject.Inject;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@Cdi(disableDiscovery = true, classes = MyService.class)
+class CdiTest
+{
+ @Inject
+ private MyService service;
+
+ @Test
+ void test1()
+ {
+ doTest();
+ }
+
+ @Test
+ void test2()
+ {
+ doTest();
+ }
+
+ private void doTest()
+ {
+ assertEquals("ok", service.ok());
+ }
+}
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Base.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Base.java
new file mode 100644
index 0000000..1f2c384
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Base.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openwebbeans.junit5.reusable;
+
+import org.apache.openwebbeans.junit5.bean.MyService;
+import org.apache.webbeans.config.WebBeansContext;
+import org.junit.jupiter.api.Test;
+
+import javax.inject.Inject;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+abstract class Base {
+ private static WebBeansContext current;
+
+ @Inject
+ private MyService service;
+
+ @Test
+ void test1()
+ {
+ doTest();
+ }
+
+ @Test
+ void test2()
+ {
+ doTest();
+ }
+
+ private void doTest()
+ {
+ if (current == null)
+ {
+ current = WebBeansContext.currentInstance();
+ }
+ else
+ {
+ assertEquals(current, WebBeansContext.currentInstance());
+ }
+ assertEquals("ok", service.ok());
+ }
+}
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi1Test.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi1Test.java
new file mode 100644
index 0000000..c57de40
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi1Test.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openwebbeans.junit5.reusable;
+
+@Config
+class Cdi1Test extends Base {
+}
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi2Test.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi2Test.java
new file mode 100644
index 0000000..1771a71
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Cdi2Test.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openwebbeans.junit5.reusable;
+
+@Config
+class Cdi2Test extends Base {
+}
diff --git a/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Config.java b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Config.java
new file mode 100644
index 0000000..33d91e2
--- /dev/null
+++ b/webbeans-junit5/src/test/java/org/apache/openwebbeans/junit5/reusable/Config.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openwebbeans.junit5.reusable;
+
+import org.apache.openwebbeans.junit5.Cdi;
+import org.apache.openwebbeans.junit5.bean.MyService;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * This is a way to create an alias for a configuration with JUnit 5.
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Cdi(disableDiscovery = true, reusable = true, classes = MyService.class)
+public @interface Config
+{
+}