/core/test/com/google/inject/PrivateModuleTest.java
Java | 564 lines | 448 code | 81 blank | 35 comment | 0 complexity | 573e065805151f80a71e749d05236bd0 MD5 | raw file
- /**
- * Copyright (C) 2008 Google Inc.
- *
- * 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 com.google.inject;
- import static com.google.inject.Asserts.asModuleChain;
- import static com.google.inject.Asserts.assertContains;
- import static com.google.inject.Asserts.getDeclaringSourcePart;
- import static com.google.inject.name.Names.named;
- import com.google.common.collect.ImmutableSet;
- import com.google.inject.name.Named;
- import com.google.inject.name.Names;
- import com.google.inject.spi.Dependency;
- import com.google.inject.spi.ExposedBinding;
- import com.google.inject.spi.PrivateElements;
- import com.google.inject.util.Types;
- import junit.framework.TestCase;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.List;
- /**
- * @author jessewilson@google.com (Jesse Wilson)
- */
- public class PrivateModuleTest extends TestCase {
- public void testBasicUsage() {
- Injector injector = Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- bind(String.class).annotatedWith(named("a")).toInstance("public");
- install(new PrivateModule() {
- @Override public void configure() {
- bind(String.class).annotatedWith(named("b")).toInstance("i");
- bind(AB.class).annotatedWith(named("one")).to(AB.class);
- expose(AB.class).annotatedWith(named("one"));
- }
- });
- install(new PrivateModule() {
- @Override public void configure() {
- bind(String.class).annotatedWith(named("b")).toInstance("ii");
- bind(AB.class).annotatedWith(named("two")).to(AB.class);
- expose(AB.class).annotatedWith(named("two"));
- }
- });
- }
- });
- AB ab1 = injector.getInstance(Key.get(AB.class, named("one")));
- assertEquals("public", ab1.a);
- assertEquals("i", ab1.b);
- AB ab2 = injector.getInstance(Key.get(AB.class, named("two")));
- assertEquals("public", ab2.a);
- assertEquals("ii", ab2.b);
- }
-
- public void testWithoutPrivateModules() {
- Injector injector = Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- PrivateBinder bindA = binder().newPrivateBinder();
- bindA.bind(String.class).annotatedWith(named("a")).toInstance("i");
- bindA.expose(String.class).annotatedWith(named("a"));
- bindA.bind(String.class).annotatedWith(named("c")).toInstance("private to A");
- PrivateBinder bindB = binder().newPrivateBinder();
- bindB.bind(String.class).annotatedWith(named("b")).toInstance("ii");
- bindB.expose(String.class).annotatedWith(named("b"));
- bindB.bind(String.class).annotatedWith(named("c")).toInstance("private to B");
- }
- });
- assertEquals("i", injector.getInstance(Key.get(String.class, named("a"))));
- assertEquals("ii", injector.getInstance(Key.get(String.class, named("b"))));
- }
- public void testMisplacedExposedAnnotation() {
- try {
- Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {}
- @Provides @Exposed
- String provideString() {
- return "i";
- }
- });
- fail();
- } catch (CreationException expected) {
- assertContains(expected.getMessage(), "Cannot expose java.lang.String on a standard binder. ",
- "Exposed bindings are only applicable to private binders.",
- " at " + PrivateModuleTest.class.getName(), "provideString(PrivateModuleTest.java:");
- }
- }
- public void testMisplacedExposeStatement() {
- try {
- Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- ((PrivateBinder) binder()).expose(String.class).annotatedWith(named("a"));
- }
- });
- fail();
- } catch (CreationException expected) {
- assertContains(expected.getMessage(), "Cannot expose java.lang.String on a standard binder. ",
- "Exposed bindings are only applicable to private binders.",
- " at " + PrivateModuleTest.class.getName(), getDeclaringSourcePart(getClass()));
- }
- }
- public void testPrivateModulesAndProvidesMethods() {
- Injector injector = Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- install(new PrivateModule() {
- @Override public void configure() {
- expose(String.class).annotatedWith(named("a"));
- }
- @Provides @Named("a") String providePublicA() {
- return "i";
- }
- @Provides @Named("b") String providePrivateB() {
- return "private";
- }
- });
- install(new PrivateModule() {
- @Override public void configure() {}
- @Provides @Named("c") String providePrivateC() {
- return "private";
- }
- @Provides @Exposed @Named("d") String providePublicD() {
- return "ii";
- }
- });
- }
- });
- assertEquals("i", injector.getInstance(Key.get(String.class, named("a"))));
- try {
- injector.getInstance(Key.get(String.class, named("b")));
- fail();
- } catch(ConfigurationException expected) {
- }
- try {
- injector.getInstance(Key.get(String.class, named("c")));
- fail();
- } catch(ConfigurationException expected) {
- }
- assertEquals("ii", injector.getInstance(Key.get(String.class, named("d"))));
- }
- public void testCannotBindAKeyExportedByASibling() {
- try {
- Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- install(new PrivateModule() {
- @Override public void configure() {
- bind(String.class).toInstance("public");
- expose(String.class);
- }
- });
- install(new PrivateModule() {
- @Override public void configure() {
- bind(String.class).toInstance("private");
- }
- });
- }
- });
- fail();
- } catch (CreationException expected) {
- assertContains(expected.getMessage(),
- "A binding to java.lang.String was already configured at ",
- getClass().getName(), getDeclaringSourcePart(getClass()),
- " at " + getClass().getName(), getDeclaringSourcePart(getClass()));
- }
- }
- public void testExposeButNoBind() {
- try {
- Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- bind(String.class).annotatedWith(named("a")).toInstance("a");
- bind(String.class).annotatedWith(named("b")).toInstance("b");
- install(new PrivateModule() {
- @Override public void configure() {
- expose(AB.class);
- }
- });
- }
- });
- fail("AB was exposed but not bound");
- } catch (CreationException expected) {
- assertContains(expected.getMessage(),
- "Could not expose() " + AB.class.getName() + ", it must be explicitly bound",
- getDeclaringSourcePart(getClass()));
- }
- }
- /**
- * Ensure that when we've got errors in different private modules, Guice presents all errors
- * in a unified message.
- */
- public void testMessagesFromPrivateModulesAreNicelyIntegrated() {
- try {
- Guice.createInjector(
- new PrivateModule() {
- @Override public void configure() {
- bind(C.class);
- }
- },
- new PrivateModule() {
- @Override public void configure() {
- bind(AB.class);
- }
- }
- );
- fail();
- } catch (CreationException expected) {
- assertContains(expected.getMessage(),
- "1) No implementation for " + C.class.getName() + " was bound.",
- "at " + getClass().getName(), getDeclaringSourcePart(getClass()),
- "2) No implementation for " + String.class.getName(), "Named(value=a) was bound.",
- "for field at " + AB.class.getName() + ".a(PrivateModuleTest.java:",
- "3) No implementation for " + String.class.getName(), "Named(value=b) was bound.",
- "for field at " + AB.class.getName() + ".b(PrivateModuleTest.java:",
- "3 errors");
- }
- }
- public void testNestedPrivateInjectors() {
- Injector injector = Guice.createInjector(new PrivateModule() {
- @Override public void configure() {
- expose(String.class);
- install(new PrivateModule() {
- @Override public void configure() {
- bind(String.class).toInstance("nested");
- expose(String.class);
- }
- });
- }
- });
- assertEquals("nested", injector.getInstance(String.class));
- }
- public void testInstallingRegularModulesFromPrivateModules() {
- Injector injector = Guice.createInjector(new PrivateModule() {
- @Override public void configure() {
- expose(String.class);
- install(new AbstractModule() {
- @Override protected void configure() {
- bind(String.class).toInstance("nested");
- }
- });
- }
- });
- assertEquals("nested", injector.getInstance(String.class));
- }
- public void testNestedPrivateModulesWithSomeKeysUnexposed() {
- Injector injector = Guice.createInjector(new PrivateModule() {
- @Override public void configure() {
- bind(String.class).annotatedWith(named("bound outer, exposed outer")).toInstance("boeo");
- expose(String.class).annotatedWith(named("bound outer, exposed outer"));
- bind(String.class).annotatedWith(named("bound outer, exposed none")).toInstance("boen");
- expose(String.class).annotatedWith(named("bound inner, exposed both"));
- install(new PrivateModule() {
- @Override public void configure() {
- bind(String.class).annotatedWith(named("bound inner, exposed both")).toInstance("bieb");
- expose(String.class).annotatedWith(named("bound inner, exposed both"));
- bind(String.class).annotatedWith(named("bound inner, exposed none")).toInstance("bien");
- }
- });
- }
- });
- assertEquals("boeo",
- injector.getInstance(Key.get(String.class, named("bound outer, exposed outer"))));
- assertEquals("bieb",
- injector.getInstance(Key.get(String.class, named("bound inner, exposed both"))));
- try {
- injector.getInstance(Key.get(String.class, named("bound outer, exposed none")));
- fail();
- } catch (ConfigurationException expected) {
- }
- try {
- injector.getInstance(Key.get(String.class, named("bound inner, exposed none")));
- fail();
- } catch (ConfigurationException expected) {
- }
- }
- public void testDependenciesBetweenPrivateAndPublic() {
- Injector injector = Guice.createInjector(
- new PrivateModule() {
- @Override protected void configure() {}
- @Provides @Exposed @Named("a") String provideA() {
- return "A";
- }
- @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) {
- return ab + "C";
- }
- },
- new AbstractModule() {
- @Override protected void configure() {}
- @Provides @Named("ab") String provideAb(@Named("a") String a) {
- return a + "B";
- }
- @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) {
- return abc + "D";
- }
- }
- );
- assertEquals("ABCD", injector.getInstance(Key.get(String.class, named("abcd"))));
- }
- public void testDependenciesBetweenPrivateAndPublicWithPublicEagerSingleton() {
- Injector injector = Guice.createInjector(
- new PrivateModule() {
- @Override protected void configure() {}
- @Provides @Exposed @Named("a") String provideA() {
- return "A";
- }
- @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) {
- return ab + "C";
- }
- },
- new AbstractModule() {
- @Override protected void configure() {
- bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider<String>() {
- @Inject @Named("abcd") String abcd;
- public String get() {
- return abcd + "E";
- }
- }).asEagerSingleton();
- }
- @Provides @Named("ab") String provideAb(@Named("a") String a) {
- return a + "B";
- }
- @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) {
- return abc + "D";
- }
- }
- );
- assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde"))));
- }
- public void testDependenciesBetweenPrivateAndPublicWithPrivateEagerSingleton() {
- Injector injector = Guice.createInjector(
- new AbstractModule() {
- @Override protected void configure() {}
- @Provides @Named("ab") String provideAb(@Named("a") String a) {
- return a + "B";
- }
- @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) {
- return abc + "D";
- }
- },
- new PrivateModule() {
- @Override protected void configure() {
- bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider<String>() {
- @Inject @Named("abcd") String abcd;
- public String get() {
- return abcd + "E";
- }
- }).asEagerSingleton();
- expose(String.class).annotatedWith(named("abcde"));
- }
- @Provides @Exposed @Named("a") String provideA() {
- return "A";
- }
- @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) {
- return ab + "C";
- }
- }
- );
- assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde"))));
- }
- static class AB {
- @Inject @Named("a") String a;
- @Inject @Named("b") String b;
- }
- interface C {}
- public void testSpiAccess() {
- Injector injector = Guice.createInjector(new PrivateModule() {
- @Override public void configure() {
- bind(String.class).annotatedWith(named("a")).toInstance("private");
- bind(String.class).annotatedWith(named("b")).toInstance("exposed");
- expose(String.class).annotatedWith(named("b"));
- }
- });
- ExposedBinding<?> binding
- = (ExposedBinding<?>) injector.getBinding(Key.get(String.class, Names.named("b")));
- assertEquals(ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class))),
- binding.getDependencies());
- PrivateElements privateElements = binding.getPrivateElements();
- assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class, named("b"))),
- privateElements.getExposedKeys());
- assertContains(privateElements.getExposedSource(Key.get(String.class, named("b"))).toString(),
- PrivateModuleTest.class.getName(), getDeclaringSourcePart(getClass()));
- Injector privateInjector = privateElements.getInjector();
- assertEquals("private", privateInjector.getInstance(Key.get(String.class, Names.named("a"))));
- }
-
- public void testParentBindsSomethingInPrivate() {
- try {
- Guice.createInjector(new FailingModule());
- fail();
- } catch(CreationException expected) {
- assertEquals(1, expected.getErrorMessages().size());
- assertContains(expected.toString(),
- "Unable to create binding for java.util.List.",
- "It was already configured on one or more child injectors or private modules",
- "bound at " + FailingPrivateModule.class.getName() + ".configure(",
- asModuleChain(FailingModule.class, ManyPrivateModules.class, FailingPrivateModule.class),
- "bound at " + SecondFailingPrivateModule.class.getName() + ".configure(",
- asModuleChain(
- FailingModule.class, ManyPrivateModules.class, SecondFailingPrivateModule.class),
- "If it was in a PrivateModule, did you forget to expose the binding?",
- "at " + FailingModule.class.getName() + ".configure(");
- }
- }
-
- public void testParentBindingToPrivateLinkedJitBinding() {
- Injector injector = Guice.createInjector(new ManyPrivateModules());
- try {
- injector.getBinding(Key.get(Types.providerOf(List.class)));
- fail();
- } catch(ConfigurationException expected) {
- assertEquals(1, expected.getErrorMessages().size());
- assertContains(expected.toString(),
- "Unable to create binding for com.google.inject.Provider<java.util.List>.",
- "It was already configured on one or more child injectors or private modules",
- "bound at " + FailingPrivateModule.class.getName() + ".configure(",
- asModuleChain(ManyPrivateModules.class, FailingPrivateModule.class),
- "bound at " + SecondFailingPrivateModule.class.getName() + ".configure(",
- asModuleChain(ManyPrivateModules.class, SecondFailingPrivateModule.class),
- "If it was in a PrivateModule, did you forget to expose the binding?",
- "while locating com.google.inject.Provider<java.util.List>");
- }
- }
-
- public void testParentBindingToPrivateJitBinding() {
- Injector injector = Guice.createInjector(new ManyPrivateModules());
- try {
- injector.getBinding(PrivateFoo.class);
- fail();
- } catch(ConfigurationException expected) {
- assertEquals(1, expected.getErrorMessages().size());
- assertContains(expected.toString(),
- "Unable to create binding for " + PrivateFoo.class.getName(),
- "It was already configured on one or more child injectors or private modules",
- "(bound by a just-in-time binding)",
- "If it was in a PrivateModule, did you forget to expose the binding?",
- "while locating " + PrivateFoo.class.getName());
- }
- }
- private static class FailingModule extends AbstractModule {
- @Override protected void configure() {
- bind(Collection.class).to(List.class);
- install(new ManyPrivateModules());
- }
- }
- private static class ManyPrivateModules extends AbstractModule {
- @Override protected void configure() {
- // make sure duplicate sources are collapsed
- install(new FailingPrivateModule());
- install(new FailingPrivateModule());
- // but additional sources are listed
- install(new SecondFailingPrivateModule());
- }
- }
- private static class FailingPrivateModule extends PrivateModule {
- @Override protected void configure() {
- bind(List.class).toInstance(new ArrayList());
-
- // Add the Provider<List> binding, created just-in-time,
- // to make sure our linked JIT bindings have the correct source.
- getProvider(Key.get(Types.providerOf(List.class)));
-
- // Request a JIT binding for PrivateFoo, which can only
- // be created in the private module because it depends
- // on List.
- getProvider(PrivateFoo.class);
- }
- }
-
- /** A second class, so we can see another name in the source list. */
- private static class SecondFailingPrivateModule extends PrivateModule {
- @Override protected void configure() {
- bind(List.class).toInstance(new ArrayList());
-
- // Add the Provider<List> binding, created just-in-time,
- // to make sure our linked JIT bindings have the correct source.
- getProvider(Key.get(Types.providerOf(List.class)));
-
- // Request a JIT binding for PrivateFoo, which can only
- // be created in the private module because it depends
- // on List.
- getProvider(PrivateFoo.class);
- }
- }
-
- private static class PrivateFoo {
- @Inject List list;
- }
- }