From 0ec986794d2ae6d4f6e3b8eefc6fefed0a019b37 Mon Sep 17 00:00:00 2001 From: Daniel Madejek Date: Wed, 1 Aug 2018 15:40:13 +0200 Subject: [PATCH 1/6] #153 PoC --- bb-junit5/pom.xml | 68 +++++++ .../qa/bb/junit5/guice/GuiceExtension.java | 184 ++++++++++++++++++ .../cognifide/qa/bb/junit5/guice/Modules.java | 47 +++++ .../junit5/guice/WebdriverCloseExtension.java | 51 +++++ .../org.junit.jupiter.api.extension.Extension | 2 + pom.xml | 17 ++ 6 files changed, 369 insertions(+) create mode 100644 bb-junit5/pom.xml create mode 100644 bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java create mode 100644 bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/Modules.java create mode 100644 bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/WebdriverCloseExtension.java create mode 100644 bb-junit5/src/main/resources/META-INF/services/org.junit.jupiter.api.extension.Extension diff --git a/bb-junit5/pom.xml b/bb-junit5/pom.xml new file mode 100644 index 00000000..8a25c15d --- /dev/null +++ b/bb-junit5/pom.xml @@ -0,0 +1,68 @@ + + + + 4.0.0 + + bobcat + com.cognifide.qa.bb + 1.4.1-SNAPSHOT + + + bb-junit5 + + + + + com.cognifide.qa.bb + bb-core + ${project.version} + + + + org.junit.jupiter + junit-jupiter-api + + + + org.junit.platform + junit-platform-commons + + + + com.google.inject + guice + + + + + + + org.apache.rat + apache-rat-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + diff --git a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java new file mode 100644 index 00000000..5feb1740 --- /dev/null +++ b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java @@ -0,0 +1,184 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2018 Cognifide Ltd. + * %% + * 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. + * #L% + */ +package com.cognifide.qa.bb.junit5.guice; + +import static java.util.stream.Collectors.toSet; +import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; +import static org.junit.platform.commons.support.AnnotationSupport.findRepeatableAnnotations; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Module; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; +import org.junit.jupiter.api.extension.ExtensionContext.Store; +import org.junit.jupiter.api.extension.TestInstancePostProcessor; + +public class GuiceExtension implements TestInstancePostProcessor { + + private static final Namespace NAMESPACE = + Namespace.create("com", "cognifide", "qa", "bb", "junit", "guice"); + + @Override + public void postProcessTestInstance(Object testInstance, ExtensionContext context) + throws Exception { + + getOrCreateInjector(context).ifPresent(injector -> injector.injectMembers(testInstance)); + + } + + private static Optional getOrCreateInjector(ExtensionContext context) + throws NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + if (!context.getElement().isPresent()) { + return Optional.empty(); + } + + AnnotatedElement element = context.getElement().get(); + Store store = context.getStore(NAMESPACE); + + Injector injector = store.get(element, Injector.class); + if (injector == null) { + injector = createInjector(context); + store.put(element, injector); + } + + return Optional.of(injector); + } + + private static Injector createInjector(ExtensionContext context) + throws NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + Optional parentInjector = getParentInjector(context); + List modules = getNewModules(context); + + return parentInjector + .map(injector -> injector.createChildInjector(modules)) + .orElseGet(() -> Guice.createInjector(modules)); + } + + private static Optional getParentInjector(ExtensionContext context) + throws NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + if (context.getParent().isPresent()) { + return getOrCreateInjector(context.getParent().get()); + } + return Optional.empty(); + } + + private static List getNewModules(ExtensionContext context) + throws NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + Set> moduleTypes = getNewModuleTypes(context); + List modules = new ArrayList<>(moduleTypes.size()); + for (Class moduleType : moduleTypes) { + Constructor moduleCtor = moduleType.getDeclaredConstructor(); + moduleCtor.setAccessible(true); + + modules.add(moduleCtor.newInstance()); + } + + context.getElement().ifPresent(element -> { + if (element instanceof Class) { + modules.add(new AbstractModule() { + @Override + protected void configure() { + requestStaticInjection((Class) element); + } + }); + } + }); + + return modules; + } + + private static Set> getNewModuleTypes(ExtensionContext context) { + if (!context.getElement().isPresent()) { + return Collections.emptySet(); + } + + Set> moduleTypes = getModuleTypes(context.getElement().get()); + context.getParent() + .map(GuiceExtension::getContextModuleTypes) + .ifPresent(moduleTypes::removeAll); + + return moduleTypes; + } + + private static Set> getContextModuleTypes(ExtensionContext context) { + return getContextModuleTypes(Optional.of(context)); + } + + /** + * Returns module types that are present on the given context or any of its enclosing contexts. + */ + private static Set> getContextModuleTypes( + Optional context) { + // TODO: Cache? + + Set> contextModuleTypes = new LinkedHashSet<>(); + while (context.isPresent() && (hasAnnotatedElement(context) || hasParent(context))) { + context + .flatMap(ExtensionContext::getElement) + .map(GuiceExtension::getModuleTypes) + .ifPresent(contextModuleTypes::addAll); + context = context.flatMap(ExtensionContext::getParent); + } + + return contextModuleTypes; + } + + private static boolean hasAnnotatedElement(Optional context) { + return context.flatMap(ExtensionContext::getElement).isPresent(); + } + + private static boolean hasParent(Optional context) { + return context.flatMap(ExtensionContext::getParent).isPresent(); + } + + private static Set> getModuleTypes(AnnotatedElement element) { + + Optional[]> classes = findAnnotation(element, Modules.class) + .map(Modules::value); + + return Arrays.stream(classes.get()).collect(toSet()); + + } +} diff --git a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/Modules.java b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/Modules.java new file mode 100644 index 00000000..e07ca1d4 --- /dev/null +++ b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/Modules.java @@ -0,0 +1,47 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2018 Cognifide Ltd. + * %% + * 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. + * #L% + */ +package com.cognifide.qa.bb.junit5.guice; + +import com.google.inject.Guice; +import com.google.inject.Module; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + *

+ * Specifies the {@link Guice} modules that define the context of the test. + *

+ *
+ * {@literal @}RunWith(TestRunner.class)
+ * {@literal @}Modules(MyModules.class)
+ *  public class MyTest {
+ *   ...
+ *  }
+ * 
+ */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Modules { + + Class[] value(); + +} diff --git a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/WebdriverCloseExtension.java b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/WebdriverCloseExtension.java new file mode 100644 index 00000000..cdbe31df --- /dev/null +++ b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/WebdriverCloseExtension.java @@ -0,0 +1,51 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2018 Cognifide Ltd. + * %% + * 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. + * #L% + */ +package com.cognifide.qa.bb.junit5.guice; + +import com.google.inject.Injector; +import com.google.inject.Key; +import java.lang.reflect.AnnotatedElement; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; +import org.junit.jupiter.api.extension.ExtensionContext.Store; +import org.openqa.selenium.WebDriver; + +public class WebdriverCloseExtension implements AfterEachCallback { + + + private static final Namespace NAMESPACE = + Namespace.create("com", "cognifide", "qa", "bb", "junit", "guice"); + + @Override + public void afterEach(ExtensionContext context) throws Exception { + if (!context.getElement().isPresent()) { + return; + } + + AnnotatedElement element = context.getElement().get(); + Store store = context.getStore(NAMESPACE); + + Injector injector = store.get(element, Injector.class); + if (injector != null) { + injector.getInstance(Key.get(WebDriver.class)).quit(); + } + } +} diff --git a/bb-junit5/src/main/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/bb-junit5/src/main/resources/META-INF/services/org.junit.jupiter.api.extension.Extension new file mode 100644 index 00000000..269cc807 --- /dev/null +++ b/bb-junit5/src/main/resources/META-INF/services/org.junit.jupiter.api.extension.Extension @@ -0,0 +1,2 @@ +com.cognifide.qa.bb.junit5.guice.GuiceExtension +com.cognifide.qa.bb.junit5.guice.WebdriverCloseExtension \ No newline at end of file diff --git a/pom.xml b/pom.xml index b34ee6aa..c7e91efc 100644 --- a/pom.xml +++ b/pom.xml @@ -62,6 +62,7 @@ limitations under the License. bb-aem-classic bb-aem-touch-ui bb-annotations + bb-junit5 @@ -95,6 +96,19 @@ limitations under the License. + + + org.junit.jupiter + junit-jupiter-api + 5.2.0 + + + + org.junit.platform + junit-platform-commons + 1.2.0 + + org.seleniumhq.selenium selenium-java @@ -307,6 +321,7 @@ limitations under the License. src/test/java/** src/main/resources/** pom.xml + > **/*.json @@ -314,6 +329,8 @@ limitations under the License. **/*.yaml **/*.properties **/*.Processor + src/main/resources/META-INF/services/** + > From 03cc86b890d2d7fa0fbfef65214197f805b817df Mon Sep 17 00:00:00 2001 From: Daniel Madejek Date: Wed, 1 Aug 2018 23:18:16 +0200 Subject: [PATCH 2/6] #153 fix for listener --- .../com/cognifide/qa/bb/RunWithJunit5.java | 34 +++++++++++++++++++ .../mapper/TestObjectTypeListener.java | 3 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 bb-core/src/main/java/com/cognifide/qa/bb/RunWithJunit5.java diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/RunWithJunit5.java b/bb-core/src/main/java/com/cognifide/qa/bb/RunWithJunit5.java new file mode 100644 index 00000000..d2a23d18 --- /dev/null +++ b/bb-core/src/main/java/com/cognifide/qa/bb/RunWithJunit5.java @@ -0,0 +1,34 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2018 Cognifide Ltd. + * %% + * 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. + * #L% + */ +package com.cognifide.qa.bb; + +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; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited +public @interface RunWithJunit5 { + + +} diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/loadable/mapper/TestObjectTypeListener.java b/bb-core/src/main/java/com/cognifide/qa/bb/loadable/mapper/TestObjectTypeListener.java index 900c1fe1..781f4a27 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/loadable/mapper/TestObjectTypeListener.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/loadable/mapper/TestObjectTypeListener.java @@ -13,6 +13,7 @@ */ package com.cognifide.qa.bb.loadable.mapper; +import com.cognifide.qa.bb.RunWithJunit5; import com.google.inject.TypeLiteral; import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeListener; @@ -40,7 +41,7 @@ public void hear(TypeLiteral type, TypeEncounter encounter) { private boolean isApplicable(Class rawType) { boolean result; - if (rawType.isAnnotationPresent(RunWith.class) + if ( (rawType.isAnnotationPresent(RunWith.class) || rawType.isAnnotationPresent(RunWithJunit5.class)) && !rawType.isAnnotationPresent(CucumberOptions.class)) { result = true; } else { From fc5fd70dd5c91765963363f7006707ca38010918 Mon Sep 17 00:00:00 2001 From: Daniel Madejek Date: Thu, 2 Aug 2018 14:57:23 +0200 Subject: [PATCH 3/6] #153 - working junit5 module --- .../qa/bb/junit5/guice/GuiceExtension.java | 4 ++ .../qa/bb/junit5/guice/InjectorUtils.java | 62 +++++++++++++++++++ .../junit5/guice/WebdriverCloseExtension.java | 21 +++---- 3 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/InjectorUtils.java diff --git a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java index 5feb1740..dcae49ce 100644 --- a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java +++ b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java @@ -43,6 +43,10 @@ import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.TestInstancePostProcessor; +/** + * Extension that will start guice and is responsible for the injections to test instance + * + */ public class GuiceExtension implements TestInstancePostProcessor { private static final Namespace NAMESPACE = diff --git a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/InjectorUtils.java b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/InjectorUtils.java new file mode 100644 index 00000000..515a065d --- /dev/null +++ b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/InjectorUtils.java @@ -0,0 +1,62 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2018 Cognifide Ltd. + * %% + * 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. + * #L% + */ +package com.cognifide.qa.bb.junit5.guice; + + +import com.google.inject.Injector; +import java.lang.reflect.AnnotatedElement; +import java.util.NoSuchElementException; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; +import org.junit.jupiter.api.extension.ExtensionContext.Store; + +/** + * Extensions helper class for retriving injector created in {@link GuiceExtension} + */ +public final class InjectorUtils { + + private InjectorUtils() { + //for util class + } + + /** + * Retrieves injector from the context store using Namespace. If it is not present it searches in + * parent context until it is found or the is end of hierachy + * + * @param context - extension context from junit5 extensions + * @param namespace - Namespace for current test invocation + * @return Injector or null if no injector is found + */ + public static Injector retrieveInjectorFromStore(ExtensionContext context, Namespace namespace) { + Injector injector = null; + AnnotatedElement element = context.getElement() + .orElseThrow(() -> new NoSuchElementException("No element present")); + Store store = context.getStore(namespace); + + injector = store.get(element, Injector.class); + if (injector == null) { + injector = retrieveInjectorFromStore( + context.getParent().orElseThrow(() -> new NoSuchElementException("No injector found")), + namespace); + } + + return injector; + } +} diff --git a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/WebdriverCloseExtension.java b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/WebdriverCloseExtension.java index cdbe31df..f5fb1baf 100644 --- a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/WebdriverCloseExtension.java +++ b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/WebdriverCloseExtension.java @@ -21,31 +21,26 @@ import com.google.inject.Injector; import com.google.inject.Key; -import java.lang.reflect.AnnotatedElement; -import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; -import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.openqa.selenium.WebDriver; -public class WebdriverCloseExtension implements AfterEachCallback { +/** + * Estension that will close webdriver after the test is executed + */ +public class WebdriverCloseExtension implements AfterTestExecutionCallback { private static final Namespace NAMESPACE = Namespace.create("com", "cognifide", "qa", "bb", "junit", "guice"); @Override - public void afterEach(ExtensionContext context) throws Exception { - if (!context.getElement().isPresent()) { - return; - } - - AnnotatedElement element = context.getElement().get(); - Store store = context.getStore(NAMESPACE); - - Injector injector = store.get(element, Injector.class); + public void afterTestExecution(ExtensionContext context) throws Exception { + Injector injector = InjectorUtils.retrieveInjectorFromStore(context, NAMESPACE); if (injector != null) { injector.getInstance(Key.get(WebDriver.class)).quit(); } } + } From 9c67d3dca9405c3e466431097b9949d1f74e82b7 Mon Sep 17 00:00:00 2001 From: Daniel Madejek Date: Thu, 2 Aug 2018 15:29:07 +0200 Subject: [PATCH 4/6] #153 javadocx and sonar fixes --- .../qa/bb/junit5/guice/GuiceExtension.java | 66 +++++++++++-------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java index dcae49ce..f3d2003a 100644 --- a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java +++ b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/GuiceExtension.java @@ -21,8 +21,8 @@ import static java.util.stream.Collectors.toSet; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; -import static org.junit.platform.commons.support.AnnotationSupport.findRepeatableAnnotations; +import com.google.common.collect.Sets; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @@ -37,15 +37,15 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.TestInstancePostProcessor; /** - * Extension that will start guice and is responsible for the injections to test instance - * + * Extension that will start guice and is responsible for the injections to test instance Based on + * Guice + * Extension */ public class GuiceExtension implements TestInstancePostProcessor { @@ -60,16 +60,18 @@ public void postProcessTestInstance(Object testInstance, ExtensionContext contex } + /** + * Create {@link Injector} or get existing one from test context + */ private static Optional getOrCreateInjector(ExtensionContext context) - throws NoSuchMethodException, - InstantiationException, - IllegalAccessException, - InvocationTargetException { - if (!context.getElement().isPresent()) { + throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { + + Optional optionalAnnotatedElement = context.getElement(); + if (!optionalAnnotatedElement.isPresent()) { return Optional.empty(); } - AnnotatedElement element = context.getElement().get(); + AnnotatedElement element = optionalAnnotatedElement.get(); Store store = context.getStore(NAMESPACE); Injector injector = store.get(element, Injector.class); @@ -81,11 +83,11 @@ private static Optional getOrCreateInjector(ExtensionContext context) return Optional.of(injector); } + /** + * Creates {@link Injector} from test context + */ private static Injector createInjector(ExtensionContext context) - throws NoSuchMethodException, - InstantiationException, - IllegalAccessException, - InvocationTargetException { + throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Optional parentInjector = getParentInjector(context); List modules = getNewModules(context); @@ -94,22 +96,23 @@ private static Injector createInjector(ExtensionContext context) .orElseGet(() -> Guice.createInjector(modules)); } + /** + * Retrieves {@link Injector} from parent test context + */ private static Optional getParentInjector(ExtensionContext context) - throws NoSuchMethodException, - InstantiationException, - IllegalAccessException, - InvocationTargetException { - if (context.getParent().isPresent()) { - return getOrCreateInjector(context.getParent().get()); + throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { + final Optional optionalParent = context.getParent(); + if (optionalParent.isPresent()) { + return getOrCreateInjector(optionalParent.get()); } return Optional.empty(); } + /** + * Gets all new {@link Module} instances for injections + */ private static List getNewModules(ExtensionContext context) - throws NoSuchMethodException, - InstantiationException, - IllegalAccessException, - InvocationTargetException { + throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Set> moduleTypes = getNewModuleTypes(context); List modules = new ArrayList<>(moduleTypes.size()); for (Class moduleType : moduleTypes) { @@ -133,12 +136,17 @@ protected void configure() { return modules; } + /** + * Returns all new {@link Module} declared in current context (returns empty set if modules where + * already declared) + */ private static Set> getNewModuleTypes(ExtensionContext context) { - if (!context.getElement().isPresent()) { + Optional optionalAnnotatedElement = context.getElement(); + if (!optionalAnnotatedElement.isPresent()) { return Collections.emptySet(); } - Set> moduleTypes = getModuleTypes(context.getElement().get()); + Set> moduleTypes = getModuleTypes(optionalAnnotatedElement.get()); context.getParent() .map(GuiceExtension::getContextModuleTypes) .ifPresent(moduleTypes::removeAll); @@ -155,7 +163,6 @@ private static Set> getContextModuleTypes(ExtensionConte */ private static Set> getContextModuleTypes( Optional context) { - // TODO: Cache? Set> contextModuleTypes = new LinkedHashSet<>(); while (context.isPresent() && (hasAnnotatedElement(context) || hasParent(context))) { @@ -182,7 +189,10 @@ private static Set> getModuleTypes(AnnotatedElement elem Optional[]> classes = findAnnotation(element, Modules.class) .map(Modules::value); - return Arrays.stream(classes.get()).collect(toSet()); + if (classes.isPresent()) { + return Arrays.stream(classes.get()).collect(toSet()); + } + return Sets.newHashSet(); } } From f3046084b753aca11ecb814d7da24b3b28fd03d1 Mon Sep 17 00:00:00 2001 From: Daniel Madejek Date: Fri, 3 Aug 2018 09:19:11 +0200 Subject: [PATCH 5/6] cr fix --- .../qa/bb/junit5/guice/InjectorUtils.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/InjectorUtils.java b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/InjectorUtils.java index 515a065d..5af52d1f 100644 --- a/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/InjectorUtils.java +++ b/bb-junit5/src/main/java/com/cognifide/qa/bb/junit5/guice/InjectorUtils.java @@ -25,7 +25,6 @@ import java.util.NoSuchElementException; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; -import org.junit.jupiter.api.extension.ExtensionContext.Store; /** * Extensions helper class for retriving injector created in {@link GuiceExtension} @@ -45,18 +44,12 @@ private InjectorUtils() { * @return Injector or null if no injector is found */ public static Injector retrieveInjectorFromStore(ExtensionContext context, Namespace namespace) { - Injector injector = null; AnnotatedElement element = context.getElement() .orElseThrow(() -> new NoSuchElementException("No element present")); - Store store = context.getStore(namespace); - injector = store.get(element, Injector.class); - if (injector == null) { - injector = retrieveInjectorFromStore( - context.getParent().orElseThrow(() -> new NoSuchElementException("No injector found")), - namespace); - } - - return injector; + return context.getStore(namespace).getOrComputeIfAbsent(element, + absent -> retrieveInjectorFromStore( + context.getParent().orElseThrow(() -> new NoSuchElementException("No injector found")), + namespace), Injector.class); } } From 446e99cc84df00939ad22f961efe65a3b111e15a Mon Sep 17 00:00:00 2001 From: Daniel Madejek Date: Fri, 3 Aug 2018 10:38:30 +0200 Subject: [PATCH 6/6] removed > --- pom.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pom.xml b/pom.xml index c7e91efc..1f305085 100644 --- a/pom.xml +++ b/pom.xml @@ -321,7 +321,6 @@ limitations under the License. src/test/java/** src/main/resources/** pom.xml - > **/*.json @@ -330,7 +329,6 @@ limitations under the License. **/*.properties **/*.Processor src/main/resources/META-INF/services/** - >