Home | History | Annotate | Download | only in inject
      1 /**
      2  * Copyright (C) 2008 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 package com.google.inject;
     19 
     20 import static com.google.inject.Asserts.assertContains;
     21 
     22 import com.google.inject.name.Named;
     23 import com.google.inject.name.Names;
     24 
     25 import junit.framework.TestCase;
     26 
     27 /**
     28  * This test verifies the ways things are injected (ie. getInstance(),
     29  * injectMembers(), bind to instance, and bind to provider instance) for all
     30  * states of optional bindings (fields, methods, multiple-argument methods,
     31  * provider fields, provider methods, constructors).
     32  *
     33  * @author jessewilson (at) google.com (Jesse Wilson)
     34  */
     35 public class OptionalBindingTest extends TestCase {
     36 
     37   private static final A injectA = new A() {};
     38   private static final B injectB = new B() {};
     39   private static final C injectC = new C() {};
     40   private static final D injectD = new D() {};
     41   private static final E injectE = new E() {};
     42   private static final F injectF = new F() {};
     43   private static final G injectG = new G() {};
     44 
     45   private Module everythingModule = new AbstractModule() {
     46     protected void configure() {
     47       bind(A.class).toInstance(injectA);
     48       bind(B.class).toInstance(injectB);
     49       bind(C.class).toInstance(injectC);
     50       bind(D.class).toInstance(injectD);
     51       bind(E.class).annotatedWith(Names.named("e")).toInstance(injectE);
     52       bind(F.class).toInstance(injectF);
     53       bind(G.class).toInstance(injectG);
     54     }
     55   };
     56 
     57   private Module partialModule = new AbstractModule() {
     58     protected void configure() {
     59       bind(C.class).toInstance(new C() {});
     60     }
     61   };
     62 
     63   private Module toInstanceModule = new AbstractModule() {
     64     protected void configure() {
     65       bind(HasOptionalInjections.class)
     66           .toInstance(new HasOptionalInjections());
     67     }
     68   };
     69 
     70   private Module toProviderInstanceModule = new AbstractModule() {
     71     protected void configure() {
     72       bind(HasOptionalInjections.class)
     73           .toProvider(new HasOptionalInjectionsProvider());
     74     }
     75   };
     76 
     77   private Module toProviderModule = new AbstractModule() {
     78     protected void configure() {
     79       bind(HasOptionalInjections.class)
     80           .toProvider(HasOptionalInjectionsProvider.class);
     81     }
     82   };
     83 
     84   public void testEverythingInjectorGetInstance() {
     85     Guice.createInjector(everythingModule)
     86         .getInstance(HasOptionalInjections.class)
     87         .assertEverythingInjected();
     88   }
     89 
     90   public void testPartialInjectorGetInstance() {
     91     Guice.createInjector(partialModule)
     92         .getInstance(HasOptionalInjections.class)
     93         .assertNothingInjected();
     94   }
     95 
     96   public void testNothingInjectorGetInstance() {
     97     Guice.createInjector()
     98         .getInstance(HasOptionalInjections.class)
     99         .assertNothingInjected();
    100   }
    101 
    102   public void testEverythingInjectorInjectMembers() {
    103     HasOptionalInjections instance = new HasOptionalInjections();
    104     Guice.createInjector(everythingModule).injectMembers(instance);
    105     instance.assertEverythingInjected();
    106   }
    107 
    108   public void testPartialInjectorInjectMembers() {
    109     HasOptionalInjections instance = new HasOptionalInjections();
    110     Guice.createInjector(partialModule).injectMembers(instance);
    111     instance.assertNothingInjected();
    112   }
    113 
    114   public void testNothingInjectorInjectMembers() {
    115     HasOptionalInjections instance = new HasOptionalInjections();
    116     Guice.createInjector().injectMembers(instance);
    117     instance.assertNothingInjected();
    118   }
    119 
    120   public void testEverythingInjectorToInstance() {
    121     Guice.createInjector(everythingModule, toInstanceModule)
    122         .getInstance(HasOptionalInjections.class)
    123         .assertEverythingInjected();
    124   }
    125 
    126   public void testPartialInjectorToInstance() {
    127     Guice.createInjector(partialModule, toInstanceModule)
    128         .getInstance(HasOptionalInjections.class)
    129         .assertNothingInjected();
    130   }
    131 
    132   public void testNothingInjectorToInstance() {
    133     Guice.createInjector(toInstanceModule)
    134         .getInstance(HasOptionalInjections.class)
    135         .assertNothingInjected();
    136   }
    137 
    138   public void testEverythingInjectorToProviderInstance() {
    139     Guice.createInjector(everythingModule, toProviderInstanceModule)
    140         .getInstance(HasOptionalInjections.class)
    141         .assertEverythingInjected();
    142   }
    143 
    144   public void testPartialInjectorToProviderInstance() {
    145     Guice.createInjector(partialModule, toProviderInstanceModule)
    146         .getInstance(HasOptionalInjections.class)
    147         .assertNothingInjected();
    148   }
    149 
    150   public void testNothingInjectorToProviderInstance() {
    151     Guice.createInjector(toProviderInstanceModule)
    152         .getInstance(HasOptionalInjections.class)
    153         .assertNothingInjected();
    154   }
    155 
    156   public void testEverythingInjectorToProvider() {
    157     Guice.createInjector(everythingModule, toProviderModule)
    158         .getInstance(HasOptionalInjections.class)
    159         .assertEverythingInjected();
    160   }
    161 
    162   public void testPartialInjectorToProvider() {
    163     Guice.createInjector(partialModule, toProviderModule)
    164         .getInstance(HasOptionalInjections.class)
    165         .assertNothingInjected();
    166   }
    167 
    168   public void testNothingInjectorToProvider() {
    169     Guice.createInjector(toProviderModule)
    170         .getInstance(HasOptionalInjections.class)
    171         .assertNothingInjected();
    172   }
    173 
    174   static class HasOptionalInjections {
    175     A originalA = new A() {};
    176     @Inject(optional=true) A a = originalA; // field injection
    177     B b; // method injection with one argument
    178     C c; // method injection with two arguments
    179     D d; // method injection with two arguments
    180     E e; // annotated injection
    181     @Inject(optional=true) Provider<F> fProvider; // provider
    182     Provider<G> gProvider; // method injection of provider
    183     boolean invoked0, invoked1, invoked2, invokedAnnotated, invokeProvider;
    184 
    185     @Inject(optional=true) void methodInjectZeroArguments() {
    186       invoked0 = true;
    187     }
    188 
    189     @Inject(optional=true) void methodInjectOneArgument(B b) {
    190       this.b = b;
    191       invoked1 = true;
    192     }
    193 
    194     @Inject(optional=true) void methodInjectTwoArguments(C c, D d) {
    195       this.c = c;
    196       this.d = d;
    197       invoked2 = true;
    198     }
    199 
    200     @Inject(optional=true) void methodInjectAnnotated(@Named("e") E e) {
    201       this.e = e;
    202       invokedAnnotated = true;
    203     }
    204 
    205     @Inject(optional=true) void methodInjectProvider(Provider<G> gProvider) {
    206       this.gProvider = gProvider;
    207       invokeProvider = true;
    208     }
    209 
    210     void assertNothingInjected() {
    211       assertSame(originalA, a);
    212       assertNull(b);
    213       assertNull(c);
    214       assertNull(d);
    215       assertNull(e);
    216       assertNull(fProvider);
    217       assertNull(gProvider);
    218       assertTrue(invoked0);
    219       assertFalse(invoked1);
    220       assertFalse(invoked2);
    221       assertFalse(invokedAnnotated);
    222     }
    223 
    224     public void assertEverythingInjected() {
    225       assertNotSame(injectA, originalA);
    226       assertSame(injectA, a);
    227       assertSame(injectB, b);
    228       assertSame(injectC, c);
    229       assertSame(injectD, d);
    230       assertSame(injectE, e);
    231       assertSame(injectF, fProvider.get());
    232       assertSame(injectG, gProvider.get());
    233       assertTrue(invoked0);
    234       assertTrue(invoked1);
    235       assertTrue(invoked2);
    236       assertTrue(invokedAnnotated);
    237     }
    238   }
    239 
    240   static class HasOptionalInjectionsProvider
    241       extends HasOptionalInjections implements Provider<HasOptionalInjections> {
    242     public HasOptionalInjections get() {
    243       return this;
    244     }
    245   }
    246 
    247   public void testOptionalConstructorBlowsUp() {
    248     try {
    249       Guice.createInjector().getInstance(HasOptionalConstructor.class);
    250       fail();
    251     } catch (ConfigurationException expected) {
    252       assertContains(expected.getMessage(), "OptionalBindingTest$HasOptionalConstructor.<init>() "
    253           + "is annotated @Inject(optional=true), but constructors cannot be optional.");
    254     }
    255   }
    256 
    257   static class HasOptionalConstructor {
    258     // Suppress compiler errors by the error-prone checker InjectedConstructorAnnotations,
    259     // which catches optional injected constructors.
    260     @SuppressWarnings("InjectedConstructorAnnotations")
    261     @Inject(optional=true)
    262     HasOptionalConstructor() {}
    263   }
    264 
    265   @Inject(optional=true) static A staticInjectA;
    266 
    267   public void testStaticInjection() {
    268     staticInjectA = injectA;
    269     Guice.createInjector(new AbstractModule() {
    270       protected void configure() {
    271         requestStaticInjection(OptionalBindingTest.class);
    272       }
    273     });
    274     assertSame(staticInjectA, injectA);
    275   }
    276 
    277   /**
    278    * Test for bug 107, where we weren't doing optional injection properly for
    279    * indirect injections.
    280    */
    281   public void testIndirectOptionalInjection() {
    282     Indirect indirect = Guice.createInjector().getInstance(Indirect.class);
    283     assertNotNull(indirect.hasOptionalInjections);
    284     indirect.hasOptionalInjections.assertNothingInjected();
    285   }
    286 
    287   static class Indirect {
    288     @Inject HasOptionalInjections hasOptionalInjections;
    289   }
    290 
    291   interface A {}
    292   interface B {}
    293   interface C {}
    294   interface D {}
    295   interface E {}
    296   interface F {}
    297   interface G {}
    298 }
    299