• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 package com.google.inject;
18 
19 import static com.google.inject.name.Names.named;
20 
21 import com.google.inject.name.Named;
22 import java.util.Arrays;
23 import java.util.List;
24 import junit.framework.TestCase;
25 
26 /** @author crazybob@google.com (Bob Lee) */
27 public class ProviderInjectionTest extends TestCase {
28 
testProviderInjection()29   public void testProviderInjection() throws CreationException {
30     Injector injector =
31         Guice.createInjector(
32             new AbstractModule() {
33               @Override
34               protected void configure() {
35                 bind(Bar.class);
36                 bind(SampleSingleton.class).in(Scopes.SINGLETON);
37               }
38             });
39 
40     Foo foo = injector.getInstance(Foo.class);
41 
42     Bar bar = foo.barProvider.get();
43     assertNotNull(bar);
44     assertNotSame(bar, foo.barProvider.get());
45 
46     SampleSingleton singleton = foo.singletonProvider.get();
47     assertNotNull(singleton);
48     assertSame(singleton, foo.singletonProvider.get());
49   }
50 
51   /** Test for bug 155. */
testProvidersAreInjectedWhenBound()52   public void testProvidersAreInjectedWhenBound() {
53     Module m =
54         new AbstractModule() {
55           @Override
56           protected void configure() {
57             bind(Bar.class)
58                 .toProvider(
59                     new Provider<Bar>() {
60                       @SuppressWarnings("unused")
61                       @Inject
62                       void cantBeCalled(Baz baz) {
63                         fail("Can't have called this method since Baz is not bound.");
64                       }
65 
66                       @Override
67                       public Bar get() {
68                         return new Bar() {};
69                       }
70                     });
71           }
72         };
73 
74     try {
75       Guice.createInjector(m);
76       fail("Should have thrown a CreationException");
77     } catch (CreationException expected) {
78     }
79   }
80 
81   /**
82    * When custom providers are used at injector creation time, they should be injected before use.
83    * In this testcase, we verify that a provider for List.class is injected before it is used.
84    */
testProvidersAreInjectedBeforeTheyAreUsed()85   public void testProvidersAreInjectedBeforeTheyAreUsed() {
86     Injector injector =
87         Guice.createInjector(
88             new AbstractModule() {
89               @Override
90               public void configure() {
91                 // should bind String to "[true]"
92                 bind(String.class)
93                     .toProvider(
94                         new Provider<String>() {
95                           private String value;
96 
97                           @Inject
98                           void initialize(List list) {
99                             value = list.toString();
100                           }
101 
102                           @Override
103                           public String get() {
104                             return value;
105                           }
106                         });
107 
108                 // should bind List to [true]
109                 bind(List.class)
110                     .toProvider(
111                         new Provider<List>() {
112                           @Inject Boolean injectedYet = Boolean.FALSE;
113 
114                           @Override
115                           public List get() {
116                             return Arrays.asList(injectedYet);
117                           }
118                         });
119 
120                 // should bind Boolean to true
121                 bind(Boolean.class).toInstance(Boolean.TRUE);
122               }
123             });
124 
125     assertEquals("Providers not injected before use", "[true]", injector.getInstance(String.class));
126   }
127 
128   /**
129    * This test ensures that regardless of binding order, instances are injected before they are
130    * used. It injects mutable Count objects and records their value at the time that they're
131    * injected.
132    */
testCreationTimeInjectionOrdering()133   public void testCreationTimeInjectionOrdering() {
134     Injector injector =
135         Guice.createInjector(
136             new AbstractModule() {
137               @Override
138               protected void configure() {
139                 // instance injection
140                 bind(Count.class)
141                     .annotatedWith(named("a"))
142                     .toInstance(
143                         new Count(0) {
144                           @Inject
145                           void initialize(@Named("b") Count bCount) {
146                             value = bCount.value + 1;
147                           }
148                         });
149 
150                 // provider injection
151                 bind(Count.class)
152                     .annotatedWith(named("b"))
153                     .toProvider(
154                         new Provider<Count>() {
155                           Count count;
156 
157                           @Inject
158                           void initialize(@Named("c") Count cCount) {
159                             count = new Count(cCount.value + 2);
160                           }
161 
162                           @Override
163                           public Count get() {
164                             return count;
165                           }
166                         });
167 
168                 // field and method injection, fields first
169                 bind(Count.class)
170                     .annotatedWith(named("c"))
171                     .toInstance(
172                         new Count(0) {
173                           @Inject
174                           @Named("d")
175                           Count dCount;
176 
177                           @Inject
178                           void initialize(@Named("e") Count eCount) {
179                             value = dCount.value + eCount.value + 4;
180                           }
181                         });
182 
183                 // static injection
184                 requestStaticInjection(StaticallyInjectable.class);
185 
186                 bind(Count.class).annotatedWith(named("d")).toInstance(new Count(8));
187                 bind(Count.class).annotatedWith(named("e")).toInstance(new Count(16));
188               }
189             });
190 
191     assertEquals(28, injector.getInstance(Key.get(Count.class, named("c"))).value);
192     assertEquals(30, injector.getInstance(Key.get(Count.class, named("b"))).value);
193     assertEquals(31, injector.getInstance(Key.get(Count.class, named("a"))).value);
194     assertEquals(28, StaticallyInjectable.cCountAtInjectionTime);
195   }
196 
197   static class Count {
198     int value;
199 
Count(int value)200     Count(int value) {
201       this.value = value;
202     }
203   }
204 
205   static class StaticallyInjectable {
206     static int cCountAtInjectionTime;
207 
208     @Inject
initialize(@amed"c") Count cCount)209     static void initialize(@Named("c") Count cCount) {
210       cCountAtInjectionTime = cCount.value;
211     }
212   }
213 
214   static class Foo {
215     @Inject Provider<Bar> barProvider;
216     @Inject Provider<SampleSingleton> singletonProvider;
217   }
218 
219   static class Bar {}
220 
221   static class SampleSingleton {}
222 
223   interface Baz {}
224 }
225