* This annotation can be repeated. + *
+ * If used on a method, the container will be reset regardless of the test lifecycle. + *
+ * The bean scope is defined as follows: + *
+ * This annotation is optional, you can instead repeat {@link AddBean}. + *
+ * E.g. + *
+ * @AddBean(FooBean.class) + * @AddBean(BarBean.class) + * class MyTest { + * } + *+ * @deprecated Use {@link io.helidon.microprofile.testing.AddBeans} instead */ +@Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) +@Deprecated(since = "4.2.0") public @interface AddBeans { /** - * Beans to be added. - * @return add bean annotations + * Get the contained annotations. + * + * @return annotations */ AddBean[] value(); } diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfig.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfig.java index a1c5c4da63a..3cb9aa8c6cb 100644 --- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfig.java +++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. + * Copyright (c) 2022, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,27 +16,40 @@ package io.helidon.microprofile.testing.junit5; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Add a configuration key/value pair to MicroProfile configuration. + * Add a configuration key/value pair to the {@link Configuration#useExisting() synthetic test configuration}. + *
* This annotation can be repeated. + *
+ * If used on a method, the container will be reset regardless of the test lifecycle. + * + * @see AddConfigs + * @see AddConfigBlock + * @see Configuration + * @deprecated Use {@link io.helidon.microprofile.testing.AddConfig} instead */ +@Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @Repeatable(AddConfigs.class) +@Deprecated(since = "4.2.0") public @interface AddConfig { /** * Configuration property key. + * * @return key */ String key(); /** * Configuration property value. + * * @return value */ String value(); diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfigBlock.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfigBlock.java index 595cb8bed1d..8a952079719 100644 --- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfigBlock.java +++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfigBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Oracle and/or its affiliates. + * Copyright (c) 2024, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,28 +23,35 @@ import java.lang.annotation.Target; /** - * Defines the configuration as a String in {@link #value()} for the - * given type. + * Add a configuration fragment to the {@link Configuration#useExisting() synthetic test configuration}. + *
+ * This annotation can be repeated. + *
+ * If used on a method, the container will be reset regardless of the test lifecycle. + * + * @see AddConfig + * @see AddConfigs + * @see Configuration + * @deprecated Use {@link io.helidon.microprofile.testing.AddConfigBlock} instead */ +@Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) -@Inherited +@Deprecated(since = "4.2.0") public @interface AddConfigBlock { - /** - * Specifies the format type of the {@link #value()}. - * - * It defaults to 'properties'. + * Specifies the configuration format. + *
+ * The default format is 'properties' * * @return the supported type */ String type() default "properties"; /** - * Configuration value. + * Configuration fragment. * - * @return String with value. + * @return fragment */ String value(); - } diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfigs.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfigs.java index 82553a8dd0f..4fbdb280e7e 100644 --- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfigs.java +++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddConfigs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. + * Copyright (c) 2022, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,22 +16,37 @@ package io.helidon.microprofile.testing.junit5; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * A repeatable container for {@link io.helidon.microprofile.testing.junit5.AddConfig}. - * No need to use this annotation, just repeat {@link io.helidon.microprofile.testing.junit5.AddConfig} annotation - * on test class. + * A repeatable container for {@link AddConfig}. + *
+ * This annotation is optional, you can instead repeat {@link AddConfig}. + *
+ * E.g. + *
+ * @AddConfig(key="foo", value="1") + * @AddConfig(key="bar", value="2") + * class MyTest { + * } + *+ * + * @see AddConfig + * @see Configuration + * @deprecated Use {@link io.helidon.microprofile.testing.AddConfigs} instead */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) +@Inherited +@Deprecated(since = "4.2.0") public @interface AddConfigs { /** - * Configuration properties to be added. + * Get the contained annotations. * - * @return properties + * @return annotations */ AddConfig[] value(); } diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddExtension.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddExtension.java index c81db4b784b..850440b812f 100644 --- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddExtension.java +++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023 Oracle and/or its affiliates. + * Copyright (c) 2020, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package io.helidon.microprofile.testing.junit5; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -24,15 +25,22 @@ import jakarta.enterprise.inject.spi.Extension; /** - * Add a CDI extension to the test container. + * Add a CDI extension to the container. + *
* This annotation can be repeated. + *
+ * If used on a method, the container will be reset regardless of the test lifecycle. + * @deprecated Use {@link io.helidon.microprofile.testing.AddExtension} instead */ +@Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @Repeatable(AddExtensions.class) +@Deprecated(since = "4.2.0") public @interface AddExtension { /** * Class of the extension to add. The class must be public. + * * @return extension class. */ Class extends Extension> value(); diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddExtensions.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddExtensions.java index 565f7f0d2f6..14b5fa99687 100644 --- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddExtensions.java +++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddExtensions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. + * Copyright (c) 2022, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,21 +16,34 @@ package io.helidon.microprofile.testing.junit5; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * A repeatable container for {@link io.helidon.microprofile.testing.junit5.AddExtension}. - * No need to use this annotation, just repeat {@link io.helidon.microprofile.testing.junit5.AddExtension} annotation - * on test class. + * A repeatable container for {@link AddExtension}. + *
+ * This annotation is optional, you can instead repeat {@link AddExtension}. + *
+ * E.g. + *
+ * @AddExtension(FooExtension.class) + * @AddExtension(BarExtension.class) + * class MyTest { + * } + *+ * @deprecated Use {@link io.helidon.microprofile.testing.AddExtensions} instead */ +@Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) +@Deprecated(since = "4.2.0") public @interface AddExtensions { /** - * Extensions to be added. - * @return extensions + * Get the contained annotations. + * + * @return annotations */ AddExtension[] value(); } diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddJaxRs.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddJaxRs.java index 1f776358f0d..6311d4e82ee 100644 --- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddJaxRs.java +++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AddJaxRs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Oracle and/or its affiliates. + * Copyright (c) 2023, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,32 @@ package io.helidon.microprofile.testing.junit5; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import io.helidon.microprofile.server.JaxRsCdiExtension; +import io.helidon.microprofile.server.ServerCdiExtension; + +import org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider; +import org.glassfish.jersey.ext.cdi1x.internal.ProcessAllAnnotatedTypes; +import org.glassfish.jersey.weld.se.WeldRequestScope; + /** - * Add JaxRS support for Request-scoped beans. + * Add JAX-RS (Jersey) support. + *
+ * If used on a method, the container will be reset regardless of the test lifecycle. + * @deprecated Use {@link io.helidon.microprofile.testing.AddJaxRs} instead */ +@Inherited @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) +@Target({ElementType.TYPE, ElementType.METHOD}) +@AddExtension(ProcessAllAnnotatedTypes.class) +@AddExtension(ServerCdiExtension.class) +@AddExtension(JaxRsCdiExtension.class) +@AddExtension(CdiComponentProvider.class) +@AddBean(WeldRequestScope.class) +@Deprecated(since = "4.2.0") public @interface AddJaxRs { } diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AfterStop.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AfterStop.java index ae3225d462a..80fdc972207 100644 --- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AfterStop.java +++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/AfterStop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Oracle and/or its affiliates. + * Copyright (c) 2023, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,14 +17,25 @@ package io.helidon.microprofile.testing.junit5; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Mark a static method to be executed after the container is stopped. + *
+ * E.g. + *
+ * @AfterStop + * static void afterStop() { + * // ... + * }+ * @deprecated Use {@link io.helidon.microprofile.testing.AfterStop} instead */ +@Inherited @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) +@Deprecated(since = "4.2.0") public @interface AfterStop { } diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/Configuration.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/Configuration.java index f75de831b10..7493a480207 100644 --- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/Configuration.java +++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/Configuration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023 Oracle and/or its affiliates. + * Copyright (c) 2020, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,38 +23,55 @@ import java.lang.annotation.Target; /** - * Additional configuration of config itself. + * General setting for the test configuration. + *
+ * If used on a method, the container will be reset regardless of the test lifecycle. + * + * @see AddConfig + * @see AddConfigs + * @see AddConfigBlock + * @deprecated Use {@link io.helidon.microprofile.testing.Configuration} instead */ +@Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) -@Inherited +@Deprecated(since = "4.2.0") public @interface Configuration { /** - * If set to {@code true}, the existing (or default) MicroProfile configuration would be used. In this case it is - * important to set property {@code mp.initializer.allow=true} in order CDI container to start, when used with - * {@link HelidonTest}. - * By default uses a configuration constructed using all {@link io.helidon.microprofile.testing.junit5.AddConfig} - * annotations and {@link #configSources()}. - * When set to false and a {@link org.junit.jupiter.api.BeforeAll} method registers a custom configuration - * with {@link org.eclipse.microprofile.config.spi.ConfigProviderResolver}, the result is undefined, though - * tests have shown that the registered config may be used (as BeforeAll ordering is undefined by - * JUnit, it may be called after our extension) + * If set to {@code false}, the synthetic test configuration is used. + *
+ * The synthetic test configuration is expressed with the following: + *
+ * If set to {@code true}, only the existing (or default) MicroProfile configuration is used + * and the annotations listed previously are ignored. + *
+ * You can use {@link org.eclipse.microprofile.config.spi.ConfigProviderResolver ConfigProviderResolver} to define + * the configuration programmatically before the CDI container starts. * - * @return whether to use existing (or default) configuration, or customized one + * @return whether to use existing (or default) configuration */ boolean useExisting() default false; /** - * Class path properties config sources to add to configuration of this test class or method. + * Class-path resources to add as config sources to the synthetic test configuration. * - * @return config sources to add + * @return config sources */ String[] configSources() default {}; /** * Configuration profile. + *
+ * The default profile is 'test'
*
- * @return String with default value "test".
+ * @return profile
*/
String profile() default "test";
}
diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/ContextHelper.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/ContextHelper.java
new file mode 100644
index 00000000000..e3563d69917
--- /dev/null
+++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/ContextHelper.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing.junit5;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Optional;
+
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
+
+/**
+ * JUnit context helper.
+ */
+class ContextHelper {
+
+ private static final Namespace NAMESPACE = Namespace.create(HelidonJunitExtension.class);
+
+ private ContextHelper() {
+ }
+
+ /**
+ * Get a store.
+ *
+ * @param context context
+ * @param methods methods
+ * @return store
+ */
+ static ExtensionContext.Store store(ExtensionContext context, Method... methods) {
+ Namespace ns;
+ if (methods.length > 0) {
+ ns = NAMESPACE.append(Arrays.stream(methods)
+ .map(Method::getName)
+ .toArray());
+ } else {
+ ns = NAMESPACE;
+ }
+ return context.getStore(ns);
+ }
+
+ /**
+ * Get an object from the given store.
+ *
+ * @param store store
+ * @param type type
+ * @param name name
+ * @param
- * When discovery is enabled, the whole classpath is scanned for bean archives (jar files containing
- * {@code META-INF/beans.xml}) and all beans and extensions are added automatically.
+ * If discovery is desired, do not annotate test class with this annotation.
*
- * When discovery is disabled, CDI would only contain the CDI implementation itself and beans and extensions added
- * through annotations {@link io.helidon.microprofile.testing.junit5.AddBean} and
- * {@link io.helidon.microprofile.testing.junit5.AddExtension}
- *
- * If discovery is disabled on class level and desired on method level,
- * the value can be set to {@code false}.
+ * If used on a method, the container will be reset regardless of the test lifecycle.
+ *
+ * When disabling discovery, you are responsible for adding the beans and extensions needed to activate the features you need.
+ * You can use the following annotations to do that:
+ *
+ * See also the following "core" CDI extensions:
+ *
+ * This extension starts a CDI container and adds the test class as a bean with support for injection. The test class uses
+ * a CDI scope that follows the test lifecycle as defined by {@link org.junit.jupiter.api.TestInstance TestInstance}.
+ *
+ * The container is started lazily during test execution to ensure that it is started after all other extensions.
+ *
+ * The container can be customized with the following annotations:
+ *
+ * The configuration can be customized with the following annotations:
+ *
+ * See also {@link io.helidon.microprofile.testing.Socket}, a CDI qualifier to inject JAX-RS client or URI.
+ *
+ * The container is created per test class by default, unless
+ * {@link HelidonTest#resetPerTest()} is {@code true}, in
+ * which case the container is created per test method.
+ *
+ * The container and the configuration can be customized per method regardless of the value of
+ * {@link HelidonTest#resetPerTest()}. The container will be reset accordingly.
+ *
+ * It is not recommended to provide a {@code beans.xml} along the test classes, as it would combine beans from all tests.
+ * Instead, you should use {@link io.helidon.microprofile.testing.AddBean} to specify the beans per test or method.
+ *
+ * @see HelidonTest
*/
-class HelidonJunitExtension implements BeforeAllCallback,
- AfterAllCallback,
- BeforeEachCallback,
- AfterEachCallback,
- InvocationInterceptor,
- ParameterResolver {
- private static final Set
- * There is no need to provide {@code beans.xml} (actually it is not recommended, as it would combine beans
- * from all tests), instead use {@link io.helidon.microprofile.testing.junit5.AddBean},
- * {@link io.helidon.microprofile.testing.junit5.AddExtension},
- * and {@link io.helidon.microprofile.testing.junit5.AddConfig}
- * annotations to control the shape of the container.
- *
- * To disable automated bean and extension discovery, annotate the class with
- * {@link io.helidon.microprofile.testing.junit5.DisableDiscovery}.
+ * A shorthand to use {@link HelidonJunitExtension} with additional settings.
+ *
+ * @see HelidonJunitExtension
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@@ -43,15 +36,11 @@
@Inherited
public @interface HelidonTest {
/**
- * By default, CDI container is created once before the class is initialized and shut down
- * after. All test methods run within the same container.
- *
- * If this is set to {@code true}, a container is created per test method invocation.
- * This restricts the test in the following way:
- * 1. No injection into fields
- * 2. No injection into constructor
+ * Forces the CDI container to be initialized and shutdown for each test method.
+ *
+ * The value of {@link org.junit.jupiter.api.TestInstance TestInstance} is ignored.
*
- * @return whether to reset container per test method
+ * @return whether to reset per test method
*/
boolean resetPerTest() default false;
diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonTestContainerImpl.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonTestContainerImpl.java
new file mode 100644
index 00000000000..19ba8c68406
--- /dev/null
+++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonTestContainerImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing.junit5;
+
+import io.helidon.microprofile.testing.HelidonTestContainer;
+import io.helidon.microprofile.testing.HelidonTestInfo;
+import io.helidon.microprofile.testing.HelidonTestScope;
+
+import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource;
+
+/**
+ * Closeable test container.
+ */
+final class HelidonTestContainerImpl extends HelidonTestContainer implements CloseableResource {
+
+ HelidonTestContainerImpl(HelidonTestInfo> testInfo, HelidonTestScope testScope) {
+ super(testInfo, testScope, HelidonTestExtensionImpl::new);
+ }
+
+ @Override
+ public void close() {
+ super.close();
+ }
+}
diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonTestDescriptorImpl.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonTestDescriptorImpl.java
new file mode 100644
index 00000000000..8d774e6203e
--- /dev/null
+++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonTestDescriptorImpl.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing.junit5;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import io.helidon.microprofile.testing.HelidonTestDescriptorBase;
+
+import static io.helidon.microprofile.testing.Proxies.mirror;
+
+/**
+ * Base descriptor implementation that supports the deprecated annotations.
+ */
+@SuppressWarnings("deprecation")
+class HelidonTestDescriptorImpl
+ * The supported types are:
+ *
+ * This annotation can be used on constructor parameters, or class fields.
+ * Test method parameter injection may be supported depending on the test framework integration.
+ *
+ * Also note that the default socket name is {@code "@default"}.
+ *
+ * E.g. constructor injection:
+ *
+ * E.g. field injection:
+ *
+ * This annotation can be repeated.
+ *
+ * If used on a method, the container will be reset regardless of the test lifecycle.
+ *
+ * The bean scope is defined as follows:
+ *
+ * This annotation is optional, you can instead repeat {@link AddBean}.
+ *
+ * E.g.
+ *
+ * This annotation can be repeated.
+ *
+ * If used on a method, the container will be reset regardless of the test lifecycle.
+ *
+ * @see io.helidon.microprofile.testing.AddConfigs
+ * @see io.helidon.microprofile.testing.AddConfigBlock
+ * @see io.helidon.microprofile.testing.AddConfigSource
+ * @see io.helidon.microprofile.testing.Configuration
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Repeatable(AddConfigs.class)
+public @interface AddConfig {
+ /**
+ * Configuration property key.
+ *
+ * @return key
+ */
+ String key();
+
+ /**
+ * Configuration property value.
+ *
+ * @return value
+ */
+ String value();
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigBlock.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigBlock.java
new file mode 100644
index 00000000000..97ec4cb06e1
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigBlock.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Add a configuration fragment to the {@link Configuration#useExisting() synthetic test configuration}.
+ *
+ * This annotation can be repeated.
+ *
+ * If used on a method, the container will be reset regardless of the test lifecycle.
+ *
+ * @see AddConfig
+ * @see AddConfigs
+ * @see AddConfigSource
+ * @see Configuration
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Repeatable(AddConfigBlocks.class)
+public @interface AddConfigBlock {
+ /**
+ * Specifies the configuration format.
+ *
+ * The default format is 'properties'
+ *
+ * @return the supported type
+ */
+ String type() default "properties";
+
+ /**
+ * Configuration fragment.
+ *
+ * @return fragment
+ */
+ String value();
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigBlocks.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigBlocks.java
new file mode 100644
index 00000000000..07922350837
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigBlocks.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A repeatable container for {@link AddConfigBlock}.
+ *
+ * This annotation is optional, you can instead repeat {@link AddConfigBlock}.
+ *
+ * E.g.
+ *
+ * E.g.
+ *
+ * This annotation is optional, you can instead repeat {@link AddConfig}.
+ *
+ * E.g.
+ *
+ * This annotation can be repeated.
+ *
+ * If used on a method, the container will be reset regardless of the test lifecycle.
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Repeatable(AddExtensions.class)
+public @interface AddExtension {
+ /**
+ * Class of the extension to add. The class must be public.
+ *
+ * @return extension class.
+ */
+ Class extends Extension> value();
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddExtensions.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddExtensions.java
new file mode 100644
index 00000000000..87c9c63f55c
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddExtensions.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A repeatable container for {@link AddExtension}.
+ *
+ * This annotation is optional, you can instead repeat {@link AddExtension}.
+ *
+ * E.g.
+ *
+ * If used on a method, the container will be reset regardless of the test lifecycle.
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@AddExtension(ProcessAllAnnotatedTypes.class)
+@AddExtension(ServerCdiExtension.class)
+@AddExtension(JaxRsCdiExtension.class)
+@AddExtension(CdiComponentProvider.class)
+@AddBean(WeldRequestScope.class)
+public @interface AddJaxRs {
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AfterStop.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AfterStop.java
new file mode 100644
index 00000000000..259c27094dd
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AfterStop.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark a static method to be executed after the container is stopped.
+ *
+ * E.g.
+ *
+ * If used on a method, the container will be reset regardless of the test lifecycle.
+ *
+ * @see AddConfig
+ * @see io.helidon.microprofile.testing.AddConfigs
+ * @see io.helidon.microprofile.testing.AddConfigBlock
+ * @see io.helidon.microprofile.testing.AddConfigSource
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface Configuration {
+ /**
+ * If set to {@code false}, the synthetic test configuration is used.
+ *
+ * The synthetic test configuration is expressed with the following:
+ *
+ * If set to {@code true}, only the existing (or default) MicroProfile configuration is used
+ * and the annotations listed previously are ignored.
+ *
+ * You can use {@link org.eclipse.microprofile.config.spi.ConfigProviderResolver ConfigProviderResolver} to define
+ * the configuration programmatically before the CDI container starts.
+ *
+ * @return whether to use existing (or default) configuration
+ */
+ boolean useExisting() default false;
+
+ /**
+ * Class-path resources to add as config sources to the synthetic test configuration.
+ *
+ * @return config sources
+ */
+ String[] configSources() default {};
+
+ /**
+ * Configuration profile.
+ *
+ * The default profile is 'test'
+ *
+ * @return profile
+ */
+ String profile() default "test";
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/DisableDiscovery.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/DisableDiscovery.java
new file mode 100644
index 00000000000..59da10af48e
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/DisableDiscovery.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Disables CDI discovery.
+ *
+ * If discovery is desired, do not annotate test class with this annotation.
+ *
+ * If used on a method, the container will be reset regardless of the test lifecycle.
+ *
+ * When disabling discovery, you are responsible for adding the beans and extensions needed to activate the features you need.
+ * You can use the following annotations to do that:
+ *
+ * See also the following "core" CDI extensions:
+ *
+ * A config delegate that serves one of three config instances:
+ *
+ * This mechanism removes the need to define bootstrapping configuration when using {@link Configuration#useExisting()}.
+ *
+ * This mechanism also provides a way to update the synthetic configuration at a later stage using CDI.
+ */
+class HelidonTestConfig extends HelidonTestConfigDelegate {
+
+ private final HelidonTestConfigSynthetic syntheticConfig;
+ private final Config originalConfig;
+ private volatile Config delegate;
+
+ HelidonTestConfig(HelidonTestInfo> testInfo) {
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ ConfigProviderResolver resolver = ConfigProviderResolver.instance();
+
+ originalConfig = resolver.getConfig(cl);
+
+ // release original config
+ resolver.releaseConfig(originalConfig);
+
+ // start with bootstrap config
+ delegate = resolver.getBuilder()
+ .withSources(MpConfigSources.create(Map.of(
+ "mp.initializer.allow", "true",
+ "mp.initializer.no-warn", "true")))
+ .build();
+
+ syntheticConfig = new HelidonTestConfigSynthetic(testInfo, this::refresh);
+
+ // register delegate
+ resolver.registerConfig(this, cl);
+ }
+
+ @Override
+ Config delegate() {
+ return delegate;
+ }
+
+ /**
+ * Get the synthetic config.
+ *
+ * @return synthetic config
+ */
+ HelidonTestConfigSynthetic synthetic() {
+ return syntheticConfig;
+ }
+
+ /**
+ * Resolve the delegate.
+ */
+ void resolve() {
+ if (syntheticConfig.useExisting()) {
+ delegate = originalConfig;
+ } else {
+ delegate = syntheticConfig;
+ }
+ }
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/HelidonTestConfigDelegate.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/HelidonTestConfigDelegate.java
new file mode 100644
index 00000000000..82c40af8c3a
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/HelidonTestConfigDelegate.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import io.helidon.common.GenericType;
+import io.helidon.common.LazyValue;
+import io.helidon.config.Config;
+import io.helidon.config.ConfigMappingException;
+import io.helidon.config.ConfigValue;
+import io.helidon.config.MissingValueException;
+import io.helidon.config.spi.ConfigMapper;
+import io.helidon.config.spi.ConfigNode;
+import io.helidon.config.spi.ConfigSource;
+import io.helidon.config.spi.LazyConfigSource;
+
+/**
+ * Config delegate.
+ *
+ * Also implements a {@link Config Helidon Config} delegate backed by a {@link LazyConfigSource}
+ * to support "just in time" caching when using {@link io.helidon.config.Config Helidon Config}.
+ */
+abstract class HelidonTestConfigDelegate implements org.eclipse.microprofile.config.Config, Config {
+
+ private final LazyValue
+ *
+ *
+ *
*/
+@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
-@Inherited
+@Deprecated(since = "4.2.0")
public @interface DisableDiscovery {
/**
- * By default if you annotate a class or a method, discovery gets disabled.
+ * By default, if you annotate a class or a method, discovery gets disabled.
* If you want to override configuration on method to differ from class, you
* can configure the value to {@code false}, effectively enabling discovery.
*
* @return whether to disable discovery ({@code true}), or enable it ({@code false}). If this
- * annotation is not present, discovery is enabled
+ * annotation is not present, discovery is enabled
*/
boolean value() default true;
}
diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonJunitExtension.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonJunitExtension.java
index 9632943ab6c..c2eb96562e5 100644
--- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonJunitExtension.java
+++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/HelidonJunitExtension.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2020, 2025 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,792 +16,200 @@
package io.helidon.microprofile.testing.junit5;
-import java.io.IOException;
-import java.io.Serial;
-import java.io.StringReader;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Executable;
-import java.lang.reflect.Field;
import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.net.URL;
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-import io.helidon.common.testing.virtualthreads.PinningRecorder;
-import io.helidon.config.mp.MpConfigSources;
-import io.helidon.microprofile.server.JaxRsCdiExtension;
-import io.helidon.microprofile.server.ServerCdiExtension;
+import io.helidon.microprofile.testing.HelidonTestInfo.ClassInfo;
+import io.helidon.microprofile.testing.HelidonTestInfo.MethodInfo;
+import io.helidon.microprofile.testing.HelidonTestScope;
+import io.helidon.microprofile.testing.Instrumented;
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.enterprise.context.Dependent;
-import jakarta.enterprise.context.RequestScoped;
-import jakarta.enterprise.event.Observes;
-import jakarta.enterprise.inject.se.SeContainer;
-import jakarta.enterprise.inject.se.SeContainerInitializer;
-import jakarta.enterprise.inject.spi.AfterBeanDiscovery;
-import jakarta.enterprise.inject.spi.BeforeBeanDiscovery;
-import jakarta.enterprise.inject.spi.CDI;
-import jakarta.enterprise.inject.spi.Extension;
-import jakarta.enterprise.inject.spi.InjectionPoint;
-import jakarta.enterprise.inject.spi.ProcessInjectionPoint;
-import jakarta.enterprise.inject.spi.configurator.AnnotatedTypeConfigurator;
-import jakarta.enterprise.util.AnnotationLiteral;
-import jakarta.inject.Inject;
-import jakarta.inject.Singleton;
-import jakarta.ws.rs.client.Client;
-import jakarta.ws.rs.client.ClientBuilder;
-import jakarta.ws.rs.client.WebTarget;
-import org.eclipse.microprofile.config.Config;
-import org.eclipse.microprofile.config.spi.ConfigBuilder;
-import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
-import org.eclipse.microprofile.config.spi.ConfigSource;
-import org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
-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.TestInstance.Lifecycle;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ExtensionContext.Store;
+import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource;
import org.junit.jupiter.api.extension.InvocationInterceptor;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
-
+import org.junit.jupiter.api.extension.TestInstanceFactory;
+import org.junit.jupiter.api.extension.TestInstanceFactoryContext;
+import org.junit.jupiter.api.parallel.ExecutionMode;
+
+import static io.helidon.microprofile.testing.HelidonTestInfo.classInfo;
+import static io.helidon.microprofile.testing.HelidonTestInfo.methodInfo;
+import static io.helidon.microprofile.testing.Instrumented.instrument;
+import static io.helidon.microprofile.testing.junit5.ContextHelper.classContext;
+import static io.helidon.microprofile.testing.junit5.ContextHelper.lookup;
+import static io.helidon.microprofile.testing.junit5.ContextHelper.store;
+import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD;
/**
- * Junit5 extension to support Helidon CDI container in tests.
+ * A JUnit5 extension that integrates CDI with JUnit to support Helidon MP.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * class MyTest {
+ * private final WebTarget target;
+ *
+ * @Inject
+ * MyTest(@Socket("@default") URI uri) {
+ * target = ClientBuilder.newClient().target(uri);
+ * }
+ * }
+ *
+ *
+ * class MyTest {
+ *
+ * @Inject // optional
+ * @Socket("@default")
+ * private WebTarget target;
+ * }
+ *
+ * @deprecated Use {@link io.helidon.microprofile.testing.Socket} instead
*/
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
+@Deprecated(since = "4.2.0")
public @interface Socket {
/**
* Name of the socket.
*
- * @return String with the name of the Socket
+ * @return socket name
*/
String value();
-
}
diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/package-info.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/package-info.java
index d299e74a35e..5e997c48de9 100644
--- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/package-info.java
+++ b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023 Oracle and/or its affiliates.
+ * Copyright (c) 2020, 2025 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,8 @@
*/
/**
- * JUnit5 extension to run CDI tests.
+ * JUnit5 extension to support Helidon MP testing.
*
- * @see io.helidon.microprofile.testing.junit5.HelidonTest
+ * @see io.helidon.microprofile.testing.junit5.HelidonJunitExtension
*/
package io.helidon.microprofile.testing.junit5;
diff --git a/microprofile/testing/junit5/src/main/java/module-info.java b/microprofile/testing/junit5/src/main/java/module-info.java
index 398fc045b50..6e7474e5307 100644
--- a/microprofile/testing/junit5/src/main/java/module-info.java
+++ b/microprofile/testing/junit5/src/main/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2020, 2025 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,22 +17,11 @@
/**
* JUnit5 extension module to run CDI tests.
*/
+@SuppressWarnings("JavaModuleNaming")
module io.helidon.microprofile.testing.junit5 {
- requires io.helidon.config.mp;
- requires io.helidon.config.yaml.mp;
- requires io.helidon.microprofile.cdi;
- requires jakarta.inject;
+ requires transitive io.helidon.microprofile.testing;
requires org.junit.jupiter.api;
- requires transitive jakarta.cdi;
- requires transitive jakarta.ws.rs;
-
- requires static io.helidon.microprofile.server;
- requires static jersey.cdi1x;
- requires static jersey.weld2.se;
- requires io.helidon.common.testing.vitualthreads;
-
exports io.helidon.microprofile.testing.junit5;
-
}
diff --git a/microprofile/testing/mocking/src/main/java/io/helidon/microprofile/testing/mocking/MockBeansCdiExtension.java b/microprofile/testing/mocking/src/main/java/io/helidon/microprofile/testing/mocking/MockBeansCdiExtension.java
index 855c9ac2d89..495eb21b188 100644
--- a/microprofile/testing/mocking/src/main/java/io/helidon/microprofile/testing/mocking/MockBeansCdiExtension.java
+++ b/microprofile/testing/mocking/src/main/java/io/helidon/microprofile/testing/mocking/MockBeansCdiExtension.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2024, 2025 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@
import org.mockito.Mockito;
/**
- * CDI extension for Mocking implementation.
+ * CDI extension that supports {@link MockBean}.
*/
public class MockBeansCdiExtension implements Extension {
diff --git a/microprofile/testing/pom.xml b/microprofile/testing/pom.xml
index e89c6692c9b..75e5dbcdab5 100644
--- a/microprofile/testing/pom.xml
+++ b/microprofile/testing/pom.xml
@@ -32,6 +32,7 @@
+ *
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Repeatable(AddBeans.class)
+public @interface AddBean {
+ /**
+ * The bean class.
+ *
+ * @return bean class
+ */
+ Class> value();
+
+ /**
+ * Override the bean scope.
+ *
+ * @return scope class
+ */
+ Class extends Annotation> scope() default Annotation.class;
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddBeans.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddBeans.java
new file mode 100644
index 00000000000..3929d7c6c6e
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddBeans.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A repeatable container for {@link AddBean}.
+ *
+ * @AddBean(FooBean.class)
+ * @AddBean(BarBean.class)
+ * class MyTest {
+ * }
+ *
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface AddBeans {
+ /**
+ * Get the contained annotations.
+ *
+ * @return annotations
+ */
+ AddBean[] value();
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfig.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfig.java
new file mode 100644
index 00000000000..39ab59686ba
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfig.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Add a configuration key/value pair to the {@link Configuration#useExisting() synthetic test configuration}.
+ *
+ * @AddConfigBlock(type = "yaml", value = """
+ * foo1:
+ * bar: "value1"
+ * """)
+ * @AddConfigBlock(type = "yaml", value = """
+ * foo2:
+ * bar: "value2"
+ * """)
+ * class MyTest {
+ * }
+ *
+ *
+ * @see AddConfig
+ * @see io.helidon.microprofile.testing.AddConfigBlocks
+ * @see AddConfigSource
+ * @see Configuration
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface AddConfigBlocks {
+ /**
+ * Get the contained annotations.
+ *
+ * @return annotations
+ */
+ AddConfigBlock[] value();
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigSource.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigSource.java
new file mode 100644
index 00000000000..c3b95cfc981
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigSource.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark a static method that provides a {@link org.eclipse.microprofile.config.spi.ConfigSource ConfigSource}
+ * to add to the {@link Configuration#useExisting() synthetic test configuration}.
+ *
+ * @AddConfigSource
+ * static ConfigSource config() {
+ * return MpConfigSources.create(Map.of("foo", "bar"));
+ * }
+ *
+ * @see io.helidon.config.mp.MpConfigSources
+ * @see AddConfig
+ * @see AddConfigs
+ * @see AddConfigBlock
+ * @see Configuration
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface AddConfigSource {
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigs.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigs.java
new file mode 100644
index 00000000000..a0edc93116b
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddConfigs.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A repeatable container for {@link AddConfig}.
+ *
+ * @AddConfig(key="foo", value="1")
+ * @AddConfig(key="bar", value="2")
+ * class MyTest {
+ * }
+ *
+ *
+ * @see AddConfig
+ * @see io.helidon.microprofile.testing.AddConfigs
+ * @see AddConfigSource
+ * @see Configuration
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface AddConfigs {
+ /**
+ * Get the contained annotations.
+ *
+ * @return annotations
+ */
+ AddConfig[] value();
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddExtension.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddExtension.java
new file mode 100644
index 00000000000..271117a0fe1
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddExtension.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2020, 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import jakarta.enterprise.inject.spi.Extension;
+
+/**
+ * Add a CDI extension to the container.
+ *
+ * @AddExtension(FooExtension.class)
+ * @AddExtension(BarExtension.class)
+ * class MyTest {
+ * }
+ *
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface AddExtensions {
+ /**
+ * Get the contained annotations.
+ *
+ * @return annotations
+ */
+ AddExtension[] value();
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddJaxRs.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddJaxRs.java
new file mode 100644
index 00000000000..fd9ab0a1cbe
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/AddJaxRs.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import io.helidon.microprofile.server.JaxRsCdiExtension;
+import io.helidon.microprofile.server.ServerCdiExtension;
+
+import org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider;
+import org.glassfish.jersey.ext.cdi1x.internal.ProcessAllAnnotatedTypes;
+import org.glassfish.jersey.weld.se.WeldRequestScope;
+
+/**
+ * Add JAX-RS (Jersey) support.
+ *
+ * @AfterStop
+ * static void afterStop() {
+ * // ...
+ * }
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface AfterStop {
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/Configuration.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/Configuration.java
new file mode 100644
index 00000000000..d33947f8b8f
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/Configuration.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2020, 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * General setting for the test configuration.
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface DisableDiscovery {
+ /**
+ * By default, if you annotate a class or a method, discovery gets disabled.
+ * If you want to override configuration on method to differ from class, you
+ * can configure the value to {@code false}, effectively enabling discovery.
+ *
+ * @return whether to disable discovery ({@code true}), or enable it ({@code false}). If this
+ * annotation is not present, discovery is enabled
+ */
+ boolean value() default true;
+}
diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/HelidonTestConfig.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/HelidonTestConfig.java
new file mode 100644
index 00000000000..32a6639a600
--- /dev/null
+++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/HelidonTestConfig.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2025 Oracle and/or its affiliates.
+ *
+ * Licensed 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 io.helidon.microprofile.testing;
+
+import java.util.Map;
+
+import io.helidon.config.mp.MpConfigSources;
+
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
+
+/**
+ * Helidon test configuration.
+ *
+ *
+ * > getOptionalValues(String propertyName, Class
> asList(Class
> asList(Function
> asNodeList() throws ConfigMappingException {
+ return hdelegate.get().asNodeList();
+ }
+
+ @Override
+ public ConfigValue