Introducing new @Rule GuiceRule guice = new GuiceRule(*Module.class)
authorMichael Vorburger <vorburger@redhat.com>
Thu, 22 Sep 2016 10:57:43 +0000 (12:57 +0200)
committerMichael Vorburger <vorburger@redhat.com>
Wed, 5 Oct 2016 16:02:01 +0000 (18:02 +0200)
This simplifies & standardizes setting up Guice for tests with a JUnit
rule. -- For an existing example, please consult the AclServiceTest in
netvirt/vpnservice/aclservice/impl; the TODO there will get replaced
with a @Rule based on the GuiceRule introduced here.

Change-Id: I931037e859c76ad06525cbd359056a7639179afe
Signed-off-by: Michael Vorburger <vorburger@redhat.com>
inject-guice-testutils/pom.xml [new file with mode: 0644]
inject-guice-testutils/src/main/java/org/opendaylight/infrautils/inject/guice/testutils/GuiceModule.java [new file with mode: 0644]
inject-guice-testutils/src/main/java/org/opendaylight/infrautils/inject/guice/testutils/GuiceRule.java [new file with mode: 0644]
inject-guice-testutils/src/test/java/org/opendaylight/infrautils/inject/guice/testutils/tests/ExampleGuiceRuleTest.java [new file with mode: 0644]
inject-guice-testutils/src/test/java/org/opendaylight/infrautils/inject/guice/testutils/tests/ExamplePureGuiceTest.java [new file with mode: 0644]
inject-guice-testutils/src/test/java/org/opendaylight/infrautils/inject/guice/testutils/tests/SomeClassWithPostConstruct.java [new file with mode: 0644]
inject/pom.xml
pom.xml

diff --git a/inject-guice-testutils/pom.xml b/inject-guice-testutils/pom.xml
new file mode 100644 (file)
index 0000000..4a0bda9
--- /dev/null
@@ -0,0 +1,48 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.opendaylight.odlparent</groupId>
+    <artifactId>odlparent</artifactId>
+    <version>1.8.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <groupId>org.opendaylight.infrautils</groupId>
+  <artifactId>inject.guice.testutils</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <configuration>
+          <propertyExpansion>checkstyle.violationSeverity=error</propertyExpansion>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>javax.inject</groupId>
+      <artifactId>javax.inject</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.mycila.guice.extensions</groupId>
+      <artifactId>mycila-guice-jsr250</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+        <groupId>com.google.truth</groupId>
+        <artifactId>truth</artifactId>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/inject-guice-testutils/src/main/java/org/opendaylight/infrautils/inject/guice/testutils/GuiceModule.java b/inject-guice-testutils/src/main/java/org/opendaylight/infrautils/inject/guice/testutils/GuiceModule.java
new file mode 100644 (file)
index 0000000..7406720
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.infrautils.inject.guice.testutils;
+
+import com.google.inject.AbstractModule;
+import com.mycila.guice.ext.closeable.CloseableModule;
+import com.mycila.guice.ext.jsr250.Jsr250Module;
+
+/**
+ * Guice module with built-in Mycila Guice Extensions for JSR-250 &amp;
+ * Closeable support for {@literal @}PreDestroy &amp; {@literal @}PostConstruct.
+ *
+ * @author Michael Vorburger
+ */
+public abstract class GuiceModule extends AbstractModule {
+
+    @Override
+    protected final void configure() {
+        install(new CloseableModule());
+        install(new Jsr250Module());
+    }
+
+    protected abstract void configureBindings();
+
+}
diff --git a/inject-guice-testutils/src/main/java/org/opendaylight/infrautils/inject/guice/testutils/GuiceRule.java b/inject-guice-testutils/src/main/java/org/opendaylight/infrautils/inject/guice/testutils/GuiceRule.java
new file mode 100644 (file)
index 0000000..21cb74e
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.infrautils.inject.guice.testutils;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.Stage;
+import com.mycila.guice.ext.closeable.CloseableInjector;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+/**
+ * JUnit Rule which initializes Guice {@link Injector} for tests.
+ *
+ * <p>Usage:
+ * <pre>
+ *   public {@literal @}Rule GuiceRule guice = new GuiceRule(YourGuiceModule.class);
+ *
+ *   {@literal @}Inject SomeClass someClass;
+ * </pre>
+ *
+ * @author Michael Vorburger
+ */
+public class GuiceRule implements MethodRule {
+
+    /**
+     * Default Stage PRODUCTION.
+     * Note that this is different from Guice's DEVELOPMENT default.
+     * We do this to avoid having to declare bindings of Listeners asEagerSingleton(),
+     * because in typical OpenDaylight projects there are Listener classes which are not @Inject,
+     * but must still be created (so that they're registered).
+     * @see <a href="https://github.com/google/guice/wiki/Bootstrap">Guice documentation</a>.
+     */
+    protected static final Stage DEFAULT_STAGE = Stage.PRODUCTION;
+
+    protected final Iterable<? extends Module> modules;
+    protected final Stage stage;
+
+    protected Injector injector;
+
+    public GuiceRule(Module... modules) {
+        this(DEFAULT_STAGE, modules);
+    }
+
+    protected GuiceRule(Stage stage, Module... modules) {
+        this.modules = Arrays.asList(modules);
+        this.stage = stage;
+    }
+
+    @SafeVarargs
+    public GuiceRule(Class<? extends Module>... moduleClasses) {
+        this.modules = createModules(Arrays.asList(moduleClasses));
+        this.stage = DEFAULT_STAGE;
+    }
+
+    protected Iterable<? extends Module> createModules(List<Class<? extends Module>> moduleClasses) {
+        return moduleClasses.stream().map(klass -> {
+            try {
+                return klass.newInstance();
+            } catch (InstantiationException | IllegalAccessException e) {
+                throw new IllegalArgumentException("newInstance() failed: " + klass.getName(), e);
+            }
+        }).collect(Collectors.toList());
+    }
+
+    @Override
+    public Statement apply(Statement base, FrameworkMethod method, Object target) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                try {
+                    setUpGuice(target);
+                    base.evaluate();
+                } finally {
+                    tearDownGuice();
+                }
+            }
+        };
+    }
+
+    protected void setUpGuice(Object target) {
+        injector = Guice.createInjector(stage, modules);
+        injector.injectMembers(target);
+    }
+
+    protected void tearDownGuice() {
+        if (injector != null) {
+            // http://code.mycila.com/guice/#3-jsr-250
+            injector.getInstance(CloseableInjector.class).close();
+        }
+    }
+
+}
diff --git a/inject-guice-testutils/src/test/java/org/opendaylight/infrautils/inject/guice/testutils/tests/ExampleGuiceRuleTest.java b/inject-guice-testutils/src/test/java/org/opendaylight/infrautils/inject/guice/testutils/tests/ExampleGuiceRuleTest.java
new file mode 100644 (file)
index 0000000..11eb573
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.infrautils.inject.guice.testutils.tests;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import javax.inject.Inject;
+import org.junit.Rule;
+import org.junit.Test;
+import org.opendaylight.infrautils.inject.guice.testutils.GuiceModule;
+import org.opendaylight.infrautils.inject.guice.testutils.GuiceRule;
+
+/**
+ * Example Guice Test using the {@link GuiceRule} & {@link GuiceModule}.
+ *
+ * @author Michael Vorburger
+ */
+public class ExampleGuiceRuleTest {
+
+    public @Rule GuiceRule guice = new GuiceRule(TestModule.class);
+
+    @Inject SomeClassWithPostConstruct someClass;
+
+    @Test public void testGuiceWithRule() {
+        assertThat(someClass.isInit).named("isInit").isTrue();
+    }
+
+    public static class TestModule extends GuiceModule {
+        @Override
+        protected void configureBindings() {
+            bind(SomeClassWithPostConstruct.class);
+        }
+    }
+}
diff --git a/inject-guice-testutils/src/test/java/org/opendaylight/infrautils/inject/guice/testutils/tests/ExamplePureGuiceTest.java b/inject-guice-testutils/src/test/java/org/opendaylight/infrautils/inject/guice/testutils/tests/ExamplePureGuiceTest.java
new file mode 100644 (file)
index 0000000..eed96c9
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.infrautils.inject.guice.testutils.tests;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.mycila.guice.ext.closeable.CloseableModule;
+import com.mycila.guice.ext.jsr250.Jsr250Module;
+import org.junit.Test;
+
+/**
+ * Example Guice Test without using Rule, just for illustration.
+ *
+ * @see ExampleGuiceRuleTest
+ *
+ * @author Michael Vorburger
+ */
+public class ExamplePureGuiceTest {
+
+    @Test
+    public void testPostConstruct() {
+        Injector injector = Guice.createInjector(new TestModule());
+        SomeClassWithPostConstruct someClass = injector.getInstance(SomeClassWithPostConstruct.class);
+        assertThat(someClass.isInit).named("isInit").isTrue();
+    }
+
+    static class TestModule extends AbstractModule {
+        @Override
+        protected void configure() {
+            install(new CloseableModule());
+            install(new Jsr250Module());
+            bind(SomeClassWithPostConstruct.class).asEagerSingleton();
+        }
+    }
+}
diff --git a/inject-guice-testutils/src/test/java/org/opendaylight/infrautils/inject/guice/testutils/tests/SomeClassWithPostConstruct.java b/inject-guice-testutils/src/test/java/org/opendaylight/infrautils/inject/guice/testutils/tests/SomeClassWithPostConstruct.java
new file mode 100644 (file)
index 0000000..59ef7a9
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.infrautils.inject.guice.testutils.tests;
+
+import javax.annotation.PostConstruct;
+
+class SomeClassWithPostConstruct {
+
+    boolean isInit = false;
+
+    @PostConstruct
+    public void init() {
+        isInit = true;
+    }
+
+}
index 20011b05dd48f939f6e736056705891ad3f2ce06..b22fc25ebdd846d9e8d42707cb7fa266e924cfe7 100644 (file)
   </build>
 
   <dependencies>
-    <!-- TODO Remove this when https://git.opendaylight.org/gerrit/#/c/44502/ is merged -->
     <dependency>
-        <groupId>javax.inject</groupId>
-        <artifactId>javax.inject</artifactId>
-        <version>1</version>
-      </dependency>
+      <groupId>javax.inject</groupId>
+      <artifactId>javax.inject</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+        <groupId>com.google.truth</groupId>
+        <artifactId>truth</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
diff --git a/pom.xml b/pom.xml
index 688abdc5f72b6d9934d0fc8876134ffe5a49d078..c8987d1ac14495a0a411ead86581421f0ad69822 100755 (executable)
--- a/pom.xml
+++ b/pom.xml
@@ -24,6 +24,7 @@
 
   <modules>
     <module>inject</module>
+    <module>inject-guice-testutils</module>
   </modules>
 
   <!--