PageRenderTime 50ms CodeModel.GetById 28ms app.highlight 17ms RepoModel.GetById 0ms app.codeStats 0ms

/core/test/com/google/inject/InjectorTest.java

https://gitlab.com/metamorphiccode/guice
Java | 413 lines | 314 code | 80 blank | 19 comment | 1 complexity | a4a5a3766cfdb6525c862f3bc88d468d MD5 | raw file
  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
 17package com.google.inject;
 18
 19import static com.google.inject.Asserts.assertContains;
 20import static com.google.inject.Asserts.assertNotSerializable;
 21import static java.lang.annotation.RetentionPolicy.RUNTIME;
 22
 23
 24import junit.framework.TestCase;
 25
 26import java.io.IOException;
 27import java.lang.annotation.Retention;
 28import java.util.concurrent.Callable;
 29import java.util.concurrent.ExecutionException;
 30import java.util.concurrent.ExecutorService;
 31import java.util.concurrent.Executors;
 32import java.util.concurrent.Future;
 33import java.util.concurrent.atomic.AtomicReference;
 34
 35/**
 36 * @author crazybob@google.com (Bob Lee)
 37 */
 38
 39public class InjectorTest extends TestCase {
 40
 41  @Retention(RUNTIME)
 42  @BindingAnnotation @interface Other {}
 43
 44  @Retention(RUNTIME)
 45  @BindingAnnotation @interface S {}
 46
 47  @Retention(RUNTIME)
 48  @BindingAnnotation @interface I {}
 49
 50  public void testToStringDoesNotInfinitelyRecurse() {
 51    Injector injector = Guice.createInjector(Stage.TOOL);
 52    injector.toString();
 53    injector.getBinding(Injector.class).toString();
 54  }
 55
 56  public void testProviderMethods() throws CreationException {
 57    final SampleSingleton singleton = new SampleSingleton();
 58    final SampleSingleton other = new SampleSingleton();
 59
 60    Injector injector = Guice.createInjector(new AbstractModule() {
 61      protected void configure() {
 62        bind(SampleSingleton.class).toInstance(singleton);
 63        bind(SampleSingleton.class)
 64            .annotatedWith(Other.class)
 65            .toInstance(other);
 66      }
 67    });
 68
 69    assertSame(singleton,
 70        injector.getInstance(Key.get(SampleSingleton.class)));
 71    assertSame(singleton, injector.getInstance(SampleSingleton.class));
 72
 73    assertSame(other,
 74        injector.getInstance(Key.get(SampleSingleton.class, Other.class)));
 75  }
 76
 77  static class SampleSingleton {}
 78
 79  public void testInjection() throws CreationException {
 80    Injector injector = createFooInjector();
 81    Foo foo = injector.getInstance(Foo.class);
 82
 83    assertEquals("test", foo.s);
 84    assertEquals("test", foo.bar.getTee().getS());
 85    assertSame(foo.bar, foo.copy);
 86    assertEquals(5, foo.i);
 87    assertEquals(5, foo.bar.getI());
 88
 89    // Test circular dependency.
 90    assertSame(foo.bar, foo.bar.getTee().getBar());
 91  }
 92
 93  private Injector createFooInjector() throws CreationException {
 94    return Guice.createInjector(new AbstractModule() {
 95      protected void configure() {
 96        bind(Bar.class).to(BarImpl.class);
 97        bind(Tee.class).to(TeeImpl.class);
 98        bindConstant().annotatedWith(S.class).to("test");
 99        bindConstant().annotatedWith(I.class).to(5);
100      }
101    });
102  }
103
104  public void testGetInstance() throws CreationException {
105    Injector injector = createFooInjector();
106
107    Bar bar = injector.getInstance(Key.get(Bar.class));
108    assertEquals("test", bar.getTee().getS());
109    assertEquals(5, bar.getI());
110  }
111
112  public void testIntAndIntegerAreInterchangeable()
113      throws CreationException {
114    Injector injector = Guice.createInjector(new AbstractModule() {
115      protected void configure() {
116        bindConstant().annotatedWith(I.class).to(5);
117      }
118    });
119
120    IntegerWrapper iw = injector.getInstance(IntegerWrapper.class);
121    assertEquals(5, (int) iw.i);
122  }
123
124  public void testInjectorApiIsNotSerializable() throws IOException {
125    Injector injector = Guice.createInjector();
126    assertNotSerializable(injector);
127    assertNotSerializable(injector.getProvider(String.class));
128    assertNotSerializable(injector.getBinding(String.class));
129    for (Binding<?> binding : injector.getBindings().values()) {
130      assertNotSerializable(binding);
131    }
132  }
133
134  static class IntegerWrapper {
135    @Inject @I Integer i;
136  }
137
138  static class Foo {
139
140    @Inject Bar bar;
141    @Inject Bar copy;
142
143    @Inject @S String s;
144
145    int i;
146
147    @Inject
148    void setI(@I int i) {
149      this.i = i;
150    }
151  }
152
153  interface Bar {
154
155    Tee getTee();
156    int getI();
157  }
158
159  @Singleton
160  static class BarImpl implements Bar {
161
162    @Inject @I int i;
163
164    Tee tee;
165
166    @Inject
167    void initialize(Tee tee) {
168      this.tee = tee;
169    }
170
171    public Tee getTee() {
172      return tee;
173    }
174
175    public int getI() {
176      return i;
177    }
178  }
179
180  interface Tee {
181
182    String getS();
183    Bar getBar();
184  }
185
186  static class TeeImpl implements Tee {
187
188    final String s;
189    @Inject Bar bar;
190
191    @Inject
192    TeeImpl(@S String s) {
193      this.s = s;
194    }
195
196    public String getS() {
197      return s;
198    }
199
200    public Bar getBar() {
201      return bar;
202    }
203  }
204
205  public void testInjectStatics() throws CreationException {
206    Guice.createInjector(new AbstractModule() {
207      protected void configure() {
208        bindConstant().annotatedWith(S.class).to("test");
209        bindConstant().annotatedWith(I.class).to(5);
210        requestStaticInjection(Static.class);
211      }
212    });
213
214    assertEquals("test", Static.s);
215    assertEquals(5, Static.i);
216  }
217
218  public void testInjectStaticInterface() {
219    try {
220      Guice.createInjector(new AbstractModule() {
221        protected void configure() {
222          requestStaticInjection(Interface.class);
223        }
224      });
225      fail();
226    } catch(CreationException ce) {
227      assertEquals(1, ce.getErrorMessages().size());
228      Asserts.assertContains(
229          ce.getMessage(),
230          "1) " + Interface.class.getName()
231              + " is an interface, but interfaces have no static injection points.",
232          "at " + InjectorTest.class.getName(),
233          "configure");
234    }
235  }
236
237  private static interface Interface {}
238
239  static class Static {
240
241    @Inject @I static int i;
242
243    static String s;
244
245    @Inject static void setS(@S String s) {
246      Static.s = s;
247    }
248  }
249
250  public void testPrivateInjection() throws CreationException {
251    Injector injector = Guice.createInjector(new AbstractModule() {
252      protected void configure() {
253        bind(String.class).toInstance("foo");
254        bind(int.class).toInstance(5);
255      }
256    });
257
258    Private p = injector.getInstance(Private.class);
259    assertEquals("foo", p.fromConstructor);
260    assertEquals(5, p.fromMethod);
261  }
262
263  static class Private {
264    String fromConstructor;
265    int fromMethod;
266
267    @Inject
268    private Private(String fromConstructor) {
269      this.fromConstructor = fromConstructor;
270    }
271
272    @Inject
273    private void setInt(int i) {
274      this.fromMethod = i;
275    }
276  }
277
278  public void testProtectedInjection() throws CreationException {
279    Injector injector = Guice.createInjector(new AbstractModule() {
280      protected void configure() {
281        bind(String.class).toInstance("foo");
282        bind(int.class).toInstance(5);
283      }
284    });
285
286    Protected p = injector.getInstance(Protected.class);
287    assertEquals("foo", p.fromConstructor);
288    assertEquals(5, p.fromMethod);
289  }
290
291  static class Protected {
292    String fromConstructor;
293    int fromMethod;
294
295    @Inject
296    protected Protected(String fromConstructor) {
297      this.fromConstructor = fromConstructor;
298    }
299
300    @Inject
301    protected void setInt(int i) {
302      this.fromMethod = i;
303    }
304  }
305
306  public void testInstanceInjectionHappensAfterFactoriesAreSetUp() {
307    Guice.createInjector(new AbstractModule() {
308      protected void configure() {
309        bind(Object.class).toInstance(new Object() {
310          @Inject Runnable r;
311        });
312
313        bind(Runnable.class).to(MyRunnable.class);
314      }
315    });
316  }
317
318  public void testSubtypeNotProvided() {
319    try {
320      Guice.createInjector().getInstance(Money.class);
321      fail();
322    } catch (ProvisionException expected) {
323      assertContains(expected.getMessage(),
324          Tree.class.getName() + " doesn't provide instances of " + Money.class.getName(),
325          "while locating ", Tree.class.getName(),
326          "while locating ", Money.class.getName());
327    }
328  }
329
330  public void testNotASubtype() {
331    try {
332      Guice.createInjector().getInstance(PineTree.class);
333      fail();
334    } catch (ConfigurationException expected) {
335      assertContains(expected.getMessage(),
336          Tree.class.getName() + " doesn't extend " + PineTree.class.getName(),
337          "while locating ", PineTree.class.getName());
338    }
339  }
340
341  public void testRecursiveImplementationType() {
342    try {
343      Guice.createInjector().getInstance(SeaHorse.class);
344      fail();
345    } catch (ConfigurationException expected) {
346      assertContains(expected.getMessage(),
347          "@ImplementedBy points to the same class it annotates.",
348          "while locating ", SeaHorse.class.getName());
349    }
350  }
351
352  public void testRecursiveProviderType() {
353    try {
354      Guice.createInjector().getInstance(Chicken.class);
355      fail();
356    } catch (ConfigurationException expected) {
357      assertContains(expected.getMessage(),
358          "@ProvidedBy points to the same class it annotates",
359          "while locating ", Chicken.class.getName());
360    }
361  }
362
363  static class MyRunnable implements Runnable {
364   public void run() {}
365  }
366
367  @ProvidedBy(Tree.class)
368  static class Money {}
369
370  static class Tree implements Provider<Object> {
371    public Object get() {
372      return "Money doesn't grow on trees";
373    }
374  }
375
376  @ImplementedBy(Tree.class)
377  static class PineTree extends Tree {}
378
379  @ImplementedBy(SeaHorse.class)
380  static class SeaHorse {}
381
382  @ProvidedBy(Chicken.class)
383  static class Chicken implements Provider<Chicken> {
384    public Chicken get() {
385      return this;
386    }
387  }
388
389  public void testJitBindingFromAnotherThreadDuringInjection() {
390    final ExecutorService executorService = Executors.newSingleThreadExecutor();
391    final AtomicReference<JustInTime> got = new AtomicReference<JustInTime>();
392
393    Guice.createInjector(new AbstractModule() {
394      protected void configure() {
395        requestInjection(new Object() {
396          @Inject void initialize(final Injector injector)
397              throws ExecutionException, InterruptedException {
398            Future<JustInTime> future = executorService.submit(new Callable<JustInTime>() {
399              public JustInTime call() throws Exception {
400                return injector.getInstance(JustInTime.class);
401              }
402            });
403            got.set(future.get());
404          }
405        });
406      }
407    });
408
409    assertNotNull(got.get());
410  }
411
412  static class JustInTime {}
413}