diff --git a/spring-5/pom.xml b/spring-5/pom.xml
index 2c96bae9bc..ec55a878c7 100644
--- a/spring-5/pom.xml
+++ b/spring-5/pom.xml
@@ -1,6 +1,6 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.baeldung
@@ -15,7 +15,7 @@
org.springframework.boot
spring-boot-starter-parent
2.0.0.BUILD-SNAPSHOT
-
+
@@ -58,11 +58,39 @@
h2
runtime
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit.jupiter.version}
+
+
+ org.springframework
+ spring-test
+ ${spring.test.version}
+
org.springframework.boot
spring-boot-starter-test
test
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit.jupiter.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-surefire-provider
+ ${junit.platform.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit.platform.version}
+ test
+
@@ -92,7 +120,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.19.1
+ ${maven-surefire-plugin.version}
methods
true
@@ -143,6 +171,10 @@
UTF-8
UTF-8
1.8
+ 1.0.0-M3
+ 5.0.0-M3
+ 4.3.7.RELEASE
+ 2.19.1
diff --git a/spring-5/src/main/java/com/baeldung/jupiter/MethodParameterFactory.java b/spring-5/src/main/java/com/baeldung/jupiter/MethodParameterFactory.java
new file mode 100644
index 0000000000..85bd505d11
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/jupiter/MethodParameterFactory.java
@@ -0,0 +1,46 @@
+package com.baeldung.jupiter;
+
+import org.springframework.core.MethodParameter;
+import org.springframework.core.annotation.SynthesizingMethodParameter;
+import org.springframework.util.Assert;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+
+abstract class MethodParameterFactory {
+
+ private MethodParameterFactory() {
+ }
+
+ public static MethodParameter createMethodParameter(Parameter parameter) {
+ Assert.notNull(parameter, "Parameter must not be null");
+ Executable executable = parameter.getDeclaringExecutable();
+ if (executable instanceof Method) {
+ return new MethodParameter((Method) executable, getIndex(parameter));
+ }
+ return new MethodParameter((Constructor>) executable, getIndex(parameter));
+ }
+
+ public static SynthesizingMethodParameter createSynthesizingMethodParameter(Parameter parameter) {
+ Assert.notNull(parameter, "Parameter must not be null");
+ Executable executable = parameter.getDeclaringExecutable();
+ if (executable instanceof Method) {
+ return new SynthesizingMethodParameter((Method) executable, getIndex(parameter));
+ }
+ throw new UnsupportedOperationException("Cannot create a SynthesizingMethodParameter for a constructor parameter: " + parameter);
+ }
+
+ private static int getIndex(Parameter parameter) {
+ Assert.notNull(parameter, "Parameter must not be null");
+ Executable executable = parameter.getDeclaringExecutable();
+ Parameter[] parameters = executable.getParameters();
+ for (int i = 0; i < parameters.length; i++) {
+ if (parameters[i] == parameter) {
+ return i;
+ }
+ }
+ throw new IllegalStateException(String.format("Failed to resolve index of parameter [%s] in executable [%s]", parameter, executable.toGenericString()));
+ }
+}
diff --git a/spring-5/src/main/java/com/baeldung/jupiter/ParameterAutowireUtils.java b/spring-5/src/main/java/com/baeldung/jupiter/ParameterAutowireUtils.java
new file mode 100644
index 0000000000..068c6af381
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/jupiter/ParameterAutowireUtils.java
@@ -0,0 +1,46 @@
+package com.baeldung.jupiter;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.beans.factory.config.DependencyDescriptor;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.MethodParameter;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.Optional;
+
+import static org.springframework.core.annotation.AnnotatedElementUtils.hasAnnotation;
+
+abstract class ParameterAutowireUtils {
+
+ private ParameterAutowireUtils() {
+ }
+
+ public static boolean isAutowirable(Parameter parameter) {
+ return ApplicationContext.class.isAssignableFrom(parameter.getType()) || hasAnnotation(parameter, Autowired.class) || hasAnnotation(parameter, Qualifier.class) || hasAnnotation(parameter, Value.class);
+ }
+
+ public static Object resolveDependency(Parameter parameter, Class> containingClass, ApplicationContext applicationContext) {
+
+ boolean required = findMergedAnnotation(parameter, Autowired.class)
+ .map(Autowired::required)
+ .orElse(true);
+ MethodParameter methodParameter = (parameter.getDeclaringExecutable() instanceof Method ? MethodParameterFactory.createSynthesizingMethodParameter(parameter) : MethodParameterFactory.createMethodParameter(parameter));
+ DependencyDescriptor descriptor = new DependencyDescriptor(methodParameter, required);
+ descriptor.setContainingClass(containingClass);
+
+ return applicationContext
+ .getAutowireCapableBeanFactory()
+ .resolveDependency(descriptor, null);
+ }
+
+ private static Optional findMergedAnnotation(AnnotatedElement element, Class annotationType) {
+
+ return Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(element, annotationType));
+ }
+}
diff --git a/spring-5/src/main/java/com/baeldung/jupiter/SpringExtension.java b/spring-5/src/main/java/com/baeldung/jupiter/SpringExtension.java
new file mode 100644
index 0000000000..08fa0c4768
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/jupiter/SpringExtension.java
@@ -0,0 +1,94 @@
+package com.baeldung.jupiter;
+
+import org.junit.jupiter.api.extension.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+import org.springframework.test.context.TestContextManager;
+import org.springframework.util.Assert;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+
+public class SpringExtension implements BeforeAllCallback, AfterAllCallback, TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback, ParameterResolver {
+
+ private static final ExtensionContext.Namespace namespace = ExtensionContext.Namespace.create(SpringExtension.class);
+
+ @Override
+ public void beforeAll(ContainerExtensionContext context) throws Exception {
+ getTestContextManager(context).beforeTestClass();
+ }
+
+ @Override
+ public void afterAll(ContainerExtensionContext context) throws Exception {
+ try {
+ getTestContextManager(context).afterTestClass();
+ } finally {
+ context
+ .getStore(namespace)
+ .remove(context
+ .getTestClass()
+ .get());
+ }
+ }
+
+ @Override
+ public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception {
+ getTestContextManager(context).prepareTestInstance(testInstance);
+ }
+
+ @Override
+ public void beforeEach(TestExtensionContext context) throws Exception {
+ Object testInstance = context.getTestInstance();
+ Method testMethod = context
+ .getTestMethod()
+ .get();
+ getTestContextManager(context).beforeTestMethod(testInstance, testMethod);
+ }
+
+ @Override
+ public void afterEach(TestExtensionContext context) throws Exception {
+ Object testInstance = context.getTestInstance();
+ Method testMethod = context
+ .getTestMethod()
+ .get();
+ Throwable testException = context
+ .getTestException()
+ .orElse(null);
+ getTestContextManager(context).afterTestMethod(testInstance, testMethod, testException);
+ }
+
+ @Override
+ public boolean supports(ParameterContext parameterContext, ExtensionContext extensionContext) {
+ Parameter parameter = parameterContext.getParameter();
+ Executable executable = parameter.getDeclaringExecutable();
+ return (executable instanceof Constructor && AnnotatedElementUtils.hasAnnotation(executable, Autowired.class)) || ParameterAutowireUtils.isAutowirable(parameter);
+ }
+
+ @Override
+ public Object resolve(ParameterContext parameterContext, ExtensionContext extensionContext) {
+ Parameter parameter = parameterContext.getParameter();
+ Class> testClass = extensionContext
+ .getTestClass()
+ .get();
+ ApplicationContext applicationContext = getApplicationContext(extensionContext);
+ return ParameterAutowireUtils.resolveDependency(parameter, testClass, applicationContext);
+ }
+
+ private ApplicationContext getApplicationContext(ExtensionContext context) {
+ return getTestContextManager(context)
+ .getTestContext()
+ .getApplicationContext();
+ }
+
+ private TestContextManager getTestContextManager(ExtensionContext context) {
+ Assert.notNull(context, "ExtensionContext must not be null");
+ Class> testClass = context
+ .getTestClass()
+ .get();
+ ExtensionContext.Store store = context.getStore(namespace);
+ return store.getOrComputeIfAbsent(testClass, TestContextManager::new, TestContextManager.class);
+ }
+}
diff --git a/spring-5/src/main/java/com/baeldung/jupiter/SpringJUnit5Config.java b/spring-5/src/main/java/com/baeldung/jupiter/SpringJUnit5Config.java
new file mode 100644
index 0000000000..e8b9cc500f
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/jupiter/SpringJUnit5Config.java
@@ -0,0 +1,40 @@
+package com.baeldung.jupiter;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.test.context.ContextConfiguration;
+
+import java.lang.annotation.*;
+
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface SpringJUnit5Config {
+
+ @AliasFor(annotation = ContextConfiguration.class, attribute = "classes")
+ Class>[] value() default {};
+
+ @AliasFor(annotation = ContextConfiguration.class)
+ Class>[] classes() default {};
+
+ @AliasFor(annotation = ContextConfiguration.class)
+ String[] locations() default {};
+
+ @AliasFor(annotation = ContextConfiguration.class)
+ Class extends ApplicationContextInitializer
+ extends ConfigurableApplicationContext>>[] initializers() default {};
+
+ @AliasFor(annotation = ContextConfiguration.class)
+ boolean inheritLocations() default true;
+
+ @AliasFor(annotation = ContextConfiguration.class)
+ boolean inheritInitializers() default true;
+
+ @AliasFor(annotation = ContextConfiguration.class)
+ String name() default "";
+}
diff --git a/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java b/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java
new file mode 100644
index 0000000000..a29f77c5df
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java
@@ -0,0 +1,20 @@
+package com.baeldung.jupiter;
+
+import com.baeldung.web.reactive.Task;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
+
+@Configuration
+public class TestConfig {
+
+ @Bean
+ static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
+ return new PropertySourcesPlaceholderConfigurer();
+ }
+
+ @Bean
+ Task taskName() {
+ return new Task("taskName", 1);
+ }
+}
diff --git a/spring-5/src/main/java/com/baeldung/web/reactive/Task.java b/spring-5/src/main/java/com/baeldung/web/reactive/Task.java
new file mode 100644
index 0000000000..84193d9354
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/web/reactive/Task.java
@@ -0,0 +1,31 @@
+package com.baeldung.web.reactive;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Task {
+
+ private final String name;
+
+ private final int id;
+
+ public Task(@JsonProperty("name") String name, @JsonProperty("id") int id) {
+ this.name = name;
+ this.id = id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public int getId() {
+ return this.id;
+ }
+
+ @Override
+ public String toString() {
+ return "Task{" +
+ "name='" + name + '\'' +
+ ", id=" + id +
+ '}';
+ }
+}
diff --git a/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java b/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java
index bf28ed1e7d..dda25f46f7 100644
--- a/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java
+++ b/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java
@@ -7,7 +7,7 @@ import org.springframework.boot.web.server.WebServer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
-import org.springframework.test.web.reactive.server.WebTestClient;
+//import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserters;
@@ -15,140 +15,141 @@ import org.springframework.web.reactive.function.BodyInserters;
import static org.springframework.web.reactive.function.BodyInserters.fromObject;
import static org.springframework.web.reactive.function.BodyInserters.fromResource;
+// TODO The class does not compile, WebTestClient cannot be resolved. Missing dependency?
public class FunctionalWebApplicationIntegrationTest {
- private static WebTestClient client;
- private static WebServer server;
-
- @BeforeClass
- public static void setup() throws Exception {
- server = new FunctionalWebApplication().start();
- client = WebTestClient
- .bindToServer()
- .baseUrl("http://localhost:" + server.getPort())
- .build();
- }
-
- @AfterClass
- public static void destroy() {
- server.stop();
- }
-
- @Test
- public void givenRouter_whenGetTest_thenGotHelloWorld() throws Exception {
- client
- .get()
- .uri("/test")
- .exchange()
- .expectStatus()
- .isOk()
- .expectBody(String.class)
- .value()
- .isEqualTo("helloworld");
- }
-
- @Test
- public void givenIndexFilter_whenRequestRoot_thenRewrittenToTest() throws Exception {
- client
- .get()
- .uri("/")
- .exchange()
- .expectStatus()
- .isOk()
- .expectBody(String.class)
- .value()
- .isEqualTo("helloworld");
- }
-
- @Test
- public void givenLoginForm_whenPostValidToken_thenSuccess() throws Exception {
- MultiValueMap formData = new LinkedMultiValueMap<>(1);
- formData.add("user", "baeldung");
- formData.add("token", "you_know_what_to_do");
-
- client
- .post()
- .uri("/login")
- .contentType(MediaType.APPLICATION_FORM_URLENCODED)
- .exchange(BodyInserters.fromFormData(formData))
- .expectStatus()
- .isOk()
- .expectBody(String.class)
- .value()
- .isEqualTo("welcome back!");
- }
-
- @Test
- public void givenLoginForm_whenRequestWithInvalidToken_thenFail() throws Exception {
- MultiValueMap formData = new LinkedMultiValueMap<>(2);
- formData.add("user", "baeldung");
- formData.add("token", "try_again");
-
- client
- .post()
- .uri("/login")
- .contentType(MediaType.APPLICATION_FORM_URLENCODED)
- .exchange(BodyInserters.fromFormData(formData))
- .expectStatus()
- .isBadRequest();
- }
-
- @Test
- public void givenUploadForm_whenRequestWithMultipartData_thenSuccess() throws Exception {
- Resource resource = new ClassPathResource("/baeldung-weekly.png");
- client
- .post()
- .uri("/upload")
- .contentType(MediaType.MULTIPART_FORM_DATA)
- .exchange(fromResource(resource))
- .expectStatus()
- .isOk()
- .expectBody(String.class)
- .value()
- .isEqualTo(String.valueOf(resource.contentLength()));
- }
-
- @Test
- public void givenActors_whenAddActor_thenAdded() throws Exception {
- client
- .get()
- .uri("/actor")
- .exchange()
- .expectStatus()
- .isOk()
- .expectBody(Actor.class)
- .list()
- .hasSize(2);
-
- client
- .post()
- .uri("/actor")
- .exchange(fromObject(new Actor("Clint", "Eastwood")))
- .expectStatus()
- .isOk();
-
- client
- .get()
- .uri("/actor")
- .exchange()
- .expectStatus()
- .isOk()
- .expectBody(Actor.class)
- .list()
- .hasSize(3);
- }
-
- @Test
- public void givenResources_whenAccess_thenGot() throws Exception {
- client
- .get()
- .uri("/files/hello.txt")
- .exchange()
- .expectStatus()
- .isOk()
- .expectBody(String.class)
- .value()
- .isEqualTo("hello");
- }
+// private static WebTestClient client;
+// private static WebServer server;
+//
+// @BeforeClass
+// public static void setup() throws Exception {
+// server = new FunctionalWebApplication().start();
+// client = WebTestClient
+// .bindToServer()
+// .baseUrl("http://localhost:" + server.getPort())
+// .build();
+// }
+//
+// @AfterClass
+// public static void destroy() {
+// server.stop();
+// }
+//
+// @Test
+// public void givenRouter_whenGetTest_thenGotHelloWorld() throws Exception {
+// client
+// .get()
+// .uri("/test")
+// .exchange()
+// .expectStatus()
+// .isOk()
+// .expectBody(String.class)
+// .value()
+// .isEqualTo("helloworld");
+// }
+//
+// @Test
+// public void givenIndexFilter_whenRequestRoot_thenRewrittenToTest() throws Exception {
+// client
+// .get()
+// .uri("/")
+// .exchange()
+// .expectStatus()
+// .isOk()
+// .expectBody(String.class)
+// .value()
+// .isEqualTo("helloworld");
+// }
+//
+// @Test
+// public void givenLoginForm_whenPostValidToken_thenSuccess() throws Exception {
+// MultiValueMap formData = new LinkedMultiValueMap<>(1);
+// formData.add("user", "baeldung");
+// formData.add("token", "you_know_what_to_do");
+//
+// client
+// .post()
+// .uri("/login")
+// .contentType(MediaType.APPLICATION_FORM_URLENCODED)
+// .exchange(BodyInserters.fromFormData(formData))
+// .expectStatus()
+// .isOk()
+// .expectBody(String.class)
+// .value()
+// .isEqualTo("welcome back!");
+// }
+//
+// @Test
+// public void givenLoginForm_whenRequestWithInvalidToken_thenFail() throws Exception {
+// MultiValueMap formData = new LinkedMultiValueMap<>(2);
+// formData.add("user", "baeldung");
+// formData.add("token", "try_again");
+//
+// client
+// .post()
+// .uri("/login")
+// .contentType(MediaType.APPLICATION_FORM_URLENCODED)
+// .exchange(BodyInserters.fromFormData(formData))
+// .expectStatus()
+// .isBadRequest();
+// }
+//
+// @Test
+// public void givenUploadForm_whenRequestWithMultipartData_thenSuccess() throws Exception {
+// Resource resource = new ClassPathResource("/baeldung-weekly.png");
+// client
+// .post()
+// .uri("/upload")
+// .contentType(MediaType.MULTIPART_FORM_DATA)
+// .exchange(fromResource(resource))
+// .expectStatus()
+// .isOk()
+// .expectBody(String.class)
+// .value()
+// .isEqualTo(String.valueOf(resource.contentLength()));
+// }
+//
+// @Test
+// public void givenActors_whenAddActor_thenAdded() throws Exception {
+// client
+// .get()
+// .uri("/actor")
+// .exchange()
+// .expectStatus()
+// .isOk()
+// .expectBody(Actor.class)
+// .list()
+// .hasSize(2);
+//
+// client
+// .post()
+// .uri("/actor")
+// .exchange(fromObject(new Actor("Clint", "Eastwood")))
+// .expectStatus()
+// .isOk();
+//
+// client
+// .get()
+// .uri("/actor")
+// .exchange()
+// .expectStatus()
+// .isOk()
+// .expectBody(Actor.class)
+// .list()
+// .hasSize(3);
+// }
+//
+// @Test
+// public void givenResources_whenAccess_thenGot() throws Exception {
+// client
+// .get()
+// .uri("/files/hello.txt")
+// .exchange()
+// .expectStatus()
+// .isOk()
+// .expectBody(String.class)
+// .value()
+// .isEqualTo("hello");
+// }
}
diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationTests.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationTests.java
new file mode 100644
index 0000000000..d15857e0a5
--- /dev/null
+++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationTests.java
@@ -0,0 +1,38 @@
+package com.baeldung.jupiter;
+
+import com.baeldung.web.reactive.Task;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@SpringJUnit5Config(TestConfig.class)
+@DisplayName("@SpringJUnit5Config Tests")
+class Spring5JUnit5ComposedAnnotationTests {
+
+ @Autowired
+ Task task;
+
+ @Autowired
+ List tasks;
+
+ @Test
+ @DisplayName("ApplicationContext injected into method")
+ void givenAMethodName_whenInjecting_thenApplicationContextInjectedIntoMethod(ApplicationContext applicationContext) {
+ assertNotNull(applicationContext, "ApplicationContext should have been injected into method by Spring");
+ assertEquals(this.task, applicationContext.getBean("taskName", Task.class));
+ }
+
+ @Test
+ @DisplayName("Spring @Beans injected into fields")
+ void givenAnObject_whenInjecting_thenSpringBeansInjected() {
+ assertNotNull(task, "Task should have been @Autowired by Spring");
+ assertEquals("taskName", task.getName(), "Task's name");
+ assertEquals(1, tasks.size(), "Number of Tasks in context");
+ }
+}
diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ParallelTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ParallelTest.java
new file mode 100644
index 0000000000..a060b78c93
--- /dev/null
+++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ParallelTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.jupiter;
+
+import com.baeldung.IntegrationTestExample1;
+import com.baeldung.IntegrationTestExample2;
+import org.junit.experimental.ParallelComputer;
+import org.junit.jupiter.api.Test;
+import org.junit.runner.Computer;
+import org.junit.runner.JUnitCore;
+
+public class Spring5JUnit5ParallelTest {
+
+ @Test
+ public void givenTwoTestClasses_whenJUnitRunParallel_thenTheTestsExecutingParallel() {
+ final Class>[] classes = {
+ IntegrationTestExample1.class, IntegrationTestExample2.class
+ };
+
+ JUnitCore.runClasses(new ParallelComputer(true, true), classes);
+ }
+
+ @Test
+ public void givenTwoTestClasses_whenJUnitRunParallel_thenTheTestsExecutingLinear() {
+ final Class>[] classes = {
+ IntegrationTestExample1.class, IntegrationTestExample2.class
+ };
+
+ JUnitCore.runClasses(new Computer(), classes);
+ }
+}
\ No newline at end of file
diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5Tests.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5Tests.java
new file mode 100644
index 0000000000..c4c3148b1e
--- /dev/null
+++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5Tests.java
@@ -0,0 +1,27 @@
+package com.baeldung.jupiter;
+
+import com.baeldung.web.reactive.Task;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.Test;
+
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = TestConfig.class)
+class Spring5JUnit5Tests {
+
+ @Autowired
+ Task task;
+
+ @Test
+ void givenAMethodName_whenInjecting_thenApplicationContextInjectedIntoMetho(ApplicationContext applicationContext) {
+ assertNotNull(applicationContext, "ApplicationContext should have been injected by Spring");
+ assertEquals(this.task, applicationContext.getBean("taskName", Task.class));
+ }
+}
diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5Java8NewFeaturesTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5Java8NewFeaturesTest.java
new file mode 100644
index 0000000000..36adf1f7ff
--- /dev/null
+++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5Java8NewFeaturesTest.java
@@ -0,0 +1,33 @@
+package com.baeldung.jupiter;
+
+import org.junit.jupiter.api.Test;
+import java.util.function.Supplier;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class Spring5Java8NewFeaturesTest {
+
+ @FunctionalInterface
+ public interface FunctionalInterfaceExample {
+ Result reverseString(Input input);
+ }
+
+ public class StringUtils{
+ public FunctionalInterfaceExample
+ functionLambdaString = s -> {
+ return Pattern.compile(" +").splitAsStream(s)
+ .map(word->new StringBuilder(word).reverse())
+ .collect(Collectors.joining(" "));
+ };
+ }
+
+ @Test
+ void givenStringUtil_whenSupplierCall_thenFunctionalInterfaceReverseString()
+ throws Exception {
+ Supplier stringUtilsSupplier = StringUtils::new;
+
+ assertEquals(stringUtilsSupplier.get().functionLambdaString
+ .reverseString("hello"), "olleh");
+ }
+}
diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientTest.java
new file mode 100644
index 0000000000..2252c255ee
--- /dev/null
+++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientTest.java
@@ -0,0 +1,110 @@
+package com.baeldung.jupiter;
+
+import com.baeldung.web.reactive.Task;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.http.server.reactive.HttpHandler;
+import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.ClientRequest;
+import org.springframework.web.reactive.function.client.ExchangeFunction;
+import org.springframework.web.reactive.function.client.ExchangeFunctions;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import reactor.ipc.netty.NettyContext;
+import reactor.ipc.netty.http.server.HttpServer;
+
+import java.net.URI;
+import java.time.Duration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
+import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
+
+public class Spring5ReactiveServerClientTest {
+
+ private static NettyContext nettyContext;
+
+ @BeforeAll
+ public static void setUp() throws Exception {
+ HttpServer server = HttpServer.create("localhost", 8080);
+ RouterFunction> route = RouterFunctions
+ .route(POST("/task/process"), request -> ServerResponse
+ .ok()
+ .body(request
+ .bodyToFlux(Task.class)
+ .map(ll -> new Task("TaskName", 1)), Task.class))
+ .and(RouterFunctions.route(GET("/task"), request -> ServerResponse
+ .ok()
+ .body(Mono.just("server is alive"), String.class)));
+ HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
+ ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
+ nettyContext = server
+ .newHandler(adapter)
+ .block();
+ }
+
+ @AfterAll
+ public static void shutDown() {
+ nettyContext.dispose();
+ }
+
+ @Test
+ public void givenCheckTask_whenServerHandle_thenServerResponseALiveString() throws Exception {
+ WebClient client = WebClient.create("http://localhost:8080");
+ Mono result = client
+ .get()
+ .uri("/task")
+ .exchange()
+ .then(response -> response.bodyToMono(String.class));
+
+ assertThat(result.block()).isInstanceOf(String.class);
+ }
+
+ @Test
+ public void givenThreeTasks_whenServerHandleTheTasks_thenServerResponseATask() throws Exception {
+ URI uri = URI.create("http://localhost:8080/task/process");
+ ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
+ ClientRequest request = ClientRequest
+ .method(HttpMethod.POST, uri)
+ .body(BodyInserters.fromPublisher(getLatLngs(), Task.class))
+ .build();
+
+ Flux taskResponse = exchange
+ .exchange(request)
+ .flatMap(response -> response.bodyToFlux(Task.class));
+
+ assertThat(taskResponse.blockFirst()).isInstanceOf(Task.class);
+ }
+
+ @Test
+ public void givenCheckTask_whenServerHandle_thenOragicServerResponseALiveString() throws Exception {
+ URI uri = URI.create("http://localhost:8080/task");
+ ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
+ ClientRequest request = ClientRequest
+ .method(HttpMethod.GET, uri)
+ .body(BodyInserters.fromPublisher(getLatLngs(), Task.class))
+ .build();
+
+ Flux taskResponse = exchange
+ .exchange(request)
+ .flatMap(response -> response.bodyToFlux(String.class));
+
+ assertThat(taskResponse.blockFirst()).isInstanceOf(String.class);
+ }
+
+ private static Flux getLatLngs() {
+ return Flux
+ .range(0, 3)
+ .zipWith(Flux.interval(Duration.ofSeconds(1)))
+ .map(x -> new Task("taskname", 1))
+ .doOnNext(ll -> System.out.println("Produced: {}" + ll));
+ }
+}