Skip to content

Commit

Permalink
MP Testing (#2353)
Browse files Browse the repository at this point in the history
* MP Testing
* support for per test method CDI container.
* support custom config sources
* support for constructor injection in single CDI container mode
* support for `SeContainer` parameter in per test method CDI container mode
* validations of annotations depending on mode

Signed-off-by: Tomas Langer <tomas.langer@oracle.com>
  • Loading branch information
tomas-langer committed Sep 16, 2020
1 parent 00beda0 commit d6bfedf
Show file tree
Hide file tree
Showing 31 changed files with 1,535 additions and 62 deletions.
6 changes: 6 additions & 0 deletions bom/pom.xml
Expand Up @@ -835,6 +835,12 @@
<artifactId>helidon-messaging-kafka</artifactId>
<version>${helidon.version}</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>io.helidon.microprofile.tests</groupId>
<artifactId>helidon-microprofile-tests-junit5</artifactId>
<version>${helidon.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
93 changes: 93 additions & 0 deletions docs/mp/testing/01_testing.adoc
@@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////////

Copyright (c) 2020 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.

///////////////////////////////////////////////////////////////////////////////
= Testing with JUnit5
:h1Prefix: MP
:pagename: testing
:description: Helidon Testing
:keywords: helidon, mp, test, testing
Helidon provides built-in test support for CDI testing in JUnit5.
== Dependency
[source,xml]
.Maven dependency
----
<dependency>
<groupId>io.helidon.microprofile.tests</groupId>
<artifactId>helidon-microprofile-tests-junit5</artifactId>
<scope>test</scope>
</dependency>
----
== Usage - default
A test can be annotated with `io.helidon.microprofile.tests.junit5.HelidonTest` annotation to mark it as a
CDI test. This annotation will start the CDI container before any test method is invoked, and stop it after
the last method is invoked. This annotation also enables injection into the test class itself.
In addition to this simplification, the following annotations are supported:
- `io.helidon.microprofile.tests.junit5.AddBean` - to add one or more beans to the container
(if not part of a bean archive, or when discovery is disabled)
- `io.helidon.microprofile.tests.junit5.AddExtension` - to add one or more CDI extensions to the container
(if not added through service loader, or when discovery is disabled)
- `io.helidon.microprofile.tests.junit5.AddConfig` - to add one or more configuration properties to MicroProfile config
without the need of creating a `microprofile-config.properties` file
[source,java]
.Code sample
----
@HelidonTest
@DisableDiscovery
@AddBean(MyBean.class)
@AddExtension(ConfigCdiExtension.class)
@AddConfig(key = "app.greeting", value = "TestHello")
class TestNoDiscovery {
@Inject
private MyBean myBean;
@Test
void testGreeting() {
assertThat(myBean, notNullValue());
assertThat(myBean.greeting(), is("TestHello"));
}
}
----
== Usage - per method CDI container
A test can be annotated as follows:
`@HelidonTest(resetPerTest = true)`
This will change the behavior as follows:
- A new CDI container is created for each test method invocation
- annotations to add config, beans and extension can be added for each method in addition to the class
- you cannot inject fields or constructor parameters of the test class itself (as a single instance is shared by more containers)
- you can add `SeContainer` as a method parameter of any test method and you will get the current container
== Usage - configuration
In addition to the `@AddConfig` annotation, you can also use
`@Configuration`.
This allows you to do the following:
- when `useExisting` is set to `true`, the configuration will not be changed
and current MP configuration will be used
- you can configure additional classpath properties config sources using `configSources`
8 changes: 8 additions & 0 deletions docs/sitegen.yaml
Expand Up @@ -373,6 +373,14 @@ backend:
items:
- includes:
- "mp/aot/*.adoc"
- title: "Testing"
pathprefix: "/mp/testing"
glyph:
type: "icon"
value: "thumbs_up_down"
items:
- includes:
- "mp/testing/*.adoc"
- title: "Additional resources"
items:
- title: "Javadocs"
Expand Down
5 changes: 5 additions & 0 deletions microprofile/fault-tolerance/pom.xml
Expand Up @@ -115,5 +115,10 @@
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.microprofile.tests</groupId>
<artifactId>helidon-microprofile-tests-junit5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020 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.
Expand All @@ -16,9 +16,6 @@

package io.helidon.microprofile.faulttolerance;

import javax.enterprise.inject.literal.NamedLiteral;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.spi.CDI;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
Expand All @@ -30,43 +27,30 @@
import java.util.function.Supplier;
import java.util.stream.Stream;

import io.helidon.microprofile.cdi.HelidonContainer;
import javax.enterprise.inject.literal.NamedLiteral;
import javax.enterprise.inject.spi.CDI;

import io.helidon.microprofile.tests.junit5.HelidonTest;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;

import static org.junit.jupiter.api.Assertions.fail;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.fail;

/**
* Class FaultToleranceTest.
*/
@HelidonTest
public abstract class FaultToleranceTest {

private static final long TIMEOUT = 5000;
private static final TimeUnit TIMEOUT_UNITS = TimeUnit.MILLISECONDS;

private static SeContainer cdiContainer;

private static final int NUMBER_OF_THREADS = 20;

private static Executor executor = Executors.newFixedThreadPool(NUMBER_OF_THREADS);

@BeforeAll
public static void startCdiContainer() {
cdiContainer = HelidonContainer.instance().start();
}

@AfterAll
public static void shutDownCdiContainer() {
if (cdiContainer != null) {
cdiContainer.close();
}
}

/**
* Clears all internal handlers before running each test. Latest FT spec has
* clarified that each method of each class that uses a bulkhead/breaker has
Expand All @@ -88,13 +72,13 @@ protected static <T> T newNamedBean(Class<T> beanClass) {

public static void printStatus(String message, String status) {
System.out.println(message + " -> " + status + " [Thread: "
+ Thread.currentThread().getName() + "]");
+ Thread.currentThread().getName() + "]");
}

@SuppressWarnings("unchecked")
static <T> CompletableFuture<T>[] getConcurrentCalls(Supplier<T> supplier, int size) {
return Stream.generate(
() -> CompletableFuture.supplyAsync(supplier, executor)
() -> CompletableFuture.supplyAsync(supplier, executor)
).limit(size).toArray(CompletableFuture[]::new);
}

Expand Down
5 changes: 5 additions & 0 deletions microprofile/security/pom.xml
Expand Up @@ -89,5 +89,10 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.microprofile.tests</groupId>
<artifactId>helidon-microprofile-tests-junit5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Expand Up @@ -15,26 +15,26 @@
*/
package io.helidon.microprofile.security;

import javax.enterprise.inject.se.SeContainer;
import javax.inject.Inject;

import io.helidon.microprofile.cdi.HelidonContainer;
import io.helidon.microprofile.tests.junit5.AddBean;
import io.helidon.microprofile.tests.junit5.HelidonTest;
import io.helidon.security.Security;

import org.junit.jupiter.api.Test;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

@HelidonTest
@AddBean(TestBean.class)
class InjectionTest {
@Inject
private TestBean testBean;

@Test
void testInjection() {

try (SeContainer container = HelidonContainer.instance()
.start()) {
TestBean bean = container.select(TestBean.class)
.get();
Security security = bean.getSecurity();
assertThat(security, notNullValue());
}
Security security = testBean.getSecurity();
assertThat(security, notNullValue());
}
}
Expand Up @@ -15,17 +15,13 @@
*/
package io.helidon.microprofile.security;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

import io.helidon.security.Security;

/**
* Test bean.
*/
@ApplicationScoped
public class TestBean {
@Inject
private Security security;
Expand Down
23 changes: 0 additions & 23 deletions microprofile/security/src/test/resources/META-INF/beans.xml

This file was deleted.

58 changes: 58 additions & 0 deletions microprofile/tests/junit5/pom.xml
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2020 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.
-->

<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>io.helidon.microprofile.tests</groupId>
<artifactId>tests-project</artifactId>
<version>2.0.3-SNAPSHOT</version>
</parent>

<artifactId>helidon-microprofile-tests-junit5</artifactId>
<name>Helidon Microprofile Tests JUnit5</name>

<description>
Integration with Junit5 to support tests with CDI injection
</description>

<dependencies>
<dependency>
<groupId>io.helidon.microprofile.cdi</groupId>
<artifactId>helidon-microprofile-cdi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.helidon.microprofile.config</groupId>
<artifactId>helidon-microprofile-config</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>

0 comments on commit d6bfedf

Please sign in to comment.