PageRenderTime 19ms CodeModel.GetById 2ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/metamorphiccode/guice
Java | 331 lines | 259 code | 52 blank | 20 comment | 0 complexity | 4f376cf8a502976ce13145dcb0ec7f6f MD5 | raw file
  1/*
  2Copyright (C) 2007 Google Inc.
  3
  4Licensed under the Apache License, Version 2.0 (the "License");
  5you may not use this file except in compliance with the License.
  6You may obtain a copy of the License at
  7
  8     http://www.apache.org/licenses/LICENSE-2.0
  9
 10Unless required by applicable law or agreed to in writing, software
 11distributed under the License is distributed on an "AS IS" BASIS,
 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13See the License for the specific language governing permissions and
 14limitations under the License.
 15*/
 16
 17package com.google.inject;
 18
 19import static com.google.inject.Asserts.assertContains;
 20import static com.google.inject.Asserts.getDeclaringSourcePart;
 21import static java.lang.annotation.ElementType.TYPE;
 22import static java.lang.annotation.RetentionPolicy.RUNTIME;
 23
 24import com.google.common.collect.ImmutableList;
 25import com.google.common.collect.Iterables;
 26import com.google.inject.matcher.Matchers;
 27import com.google.inject.name.Names;
 28import com.google.inject.spi.TypeConverter;
 29
 30import junit.framework.TestCase;
 31
 32import java.lang.annotation.Retention;
 33import java.lang.annotation.Target;
 34import java.util.List;
 35
 36/**
 37 * @author jessewilson@google.com (Jesse Wilson)
 38 */
 39public class ParentInjectorTest extends TestCase {
 40
 41  public void testParentAndChildCannotShareExplicitBindings() {
 42    Injector parent = Guice.createInjector(bindsA);
 43    try {
 44      parent.createChildInjector(bindsA);
 45      fail("Created the same explicit binding on both parent and child");
 46    } catch (CreationException e) {
 47      assertContains(e.getMessage(), "A binding to ", A.class.getName(), " was already configured",
 48          " at ", getClass().getName(), getDeclaringSourcePart(getClass()),
 49          " at ", getClass().getName(), getDeclaringSourcePart(getClass()));
 50    }
 51  }
 52
 53  public void testParentJitBindingWontClobberChildBinding() {
 54    Injector parent = Guice.createInjector();
 55    parent.createChildInjector(bindsA);
 56    try {
 57      parent.getInstance(A.class);
 58      fail("Created a just-in-time binding on the parent that's the same as a child's binding");
 59    } catch (ConfigurationException e) {
 60      assertContains(e.getMessage(),
 61          "Unable to create binding for " + A.class.getName(),
 62          "It was already configured on one or more child injectors or private modules",
 63          "bound at " + bindsA.getClass().getName() + ".configure(",
 64          "If it was in a PrivateModule, did you forget to expose the binding?",
 65          "while locating " + A.class.getName());
 66    }
 67  }
 68  
 69  public void testChildCannotBindToAParentJitBinding() {
 70    Injector parent = Guice.createInjector();
 71    parent.getInstance(A.class);
 72    try {
 73      parent.createChildInjector(bindsA);
 74      fail();
 75    } catch(CreationException ce) {
 76      assertContains(Iterables.getOnlyElement(ce.getErrorMessages()).getMessage(),
 77          "A just-in-time binding to " + A.class.getName() + " was already configured on a parent injector.");
 78    }    
 79  }
 80
 81  public void testJustInTimeBindingsAreSharedWithParentIfPossible() {
 82    Injector parent = Guice.createInjector();
 83    Injector child = parent.createChildInjector();
 84    assertSame(child.getInstance(A.class), parent.getInstance(A.class));
 85
 86    Injector anotherChild = parent.createChildInjector();
 87    assertSame(anotherChild.getInstance(A.class), parent.getInstance(A.class));
 88
 89    Injector grandchild = child.createChildInjector();
 90    assertSame(grandchild.getInstance(A.class), parent.getInstance(A.class));
 91  }
 92
 93  public void testBindingsInherited() {
 94    Injector parent = Guice.createInjector(bindsB);
 95    Injector child = parent.createChildInjector();
 96    assertSame(RealB.class, child.getInstance(B.class).getClass());
 97  }
 98
 99  public void testGetParent() {
100    Injector top = Guice.createInjector(bindsA);
101    Injector middle = top.createChildInjector(bindsB);
102    Injector bottom = middle.createChildInjector();
103    assertSame(middle, bottom.getParent());
104    assertSame(top, middle.getParent());
105    assertNull(top.getParent());
106  }
107
108  public void testChildBindingsNotVisibleToParent() {
109    Injector parent = Guice.createInjector();
110    parent.createChildInjector(bindsB);
111    try {
112      parent.getBinding(B.class);
113      fail();
114    } catch (ConfigurationException expected) {
115    }
116  }
117
118  public void testScopesInherited() {
119    Injector parent = Guice.createInjector(new AbstractModule() {
120      @Override protected void configure() {
121        bindScope(MyScope.class, Scopes.SINGLETON);
122      }
123    });
124    Injector child = parent.createChildInjector(new AbstractModule() {
125      @Override protected void configure() {
126        bind(A.class).in(MyScope.class);
127      }
128    });
129    assertSame(child.getInstance(A.class), child.getInstance(A.class));
130  }
131
132  /*if[AOP]*/
133  private final org.aopalliance.intercept.MethodInterceptor returnNullInterceptor
134      = new org.aopalliance.intercept.MethodInterceptor() {
135    public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) {
136      return null;
137    }
138  };
139
140  public void testInterceptorsInherited() {
141    Injector parent = Guice.createInjector(new AbstractModule() {
142      @Override protected void configure() {
143        super.bindInterceptor(Matchers.any(), Matchers.returns(Matchers.identicalTo(A.class)),
144            returnNullInterceptor);
145      }
146    });
147
148    Injector child = parent.createChildInjector(new AbstractModule() {
149      @Override protected void configure() {
150        bind(C.class);
151      }
152    });
153
154    assertNull(child.getInstance(C.class).interceptedMethod());
155  }
156  /*end[AOP]*/
157
158  public void testTypeConvertersInherited() {
159    Injector parent = Guice.createInjector(bindListConverterModule);
160    Injector child = parent.createChildInjector(bindStringNamedB);
161
162    assertEquals(ImmutableList.of(), child.getInstance(Key.get(List.class, Names.named("B"))));
163  }
164
165  public void testTypeConvertersConflicting() {
166    Injector parent = Guice.createInjector(bindListConverterModule);
167    Injector child = parent.createChildInjector(bindListConverterModule, bindStringNamedB);
168
169    try {
170      child.getInstance(Key.get(List.class, Names.named("B")));
171      fail();
172    } catch (ConfigurationException expected) {
173      Asserts.assertContains(expected.getMessage(), "Multiple converters can convert");
174    }
175  }
176
177  public void testInjectorInjectionSpanningInjectors() {
178    Injector parent = Guice.createInjector();
179    Injector child = parent.createChildInjector(new AbstractModule() {
180      @Override protected void configure() {
181        bind(D.class);
182      }
183    });
184
185    D d = child.getInstance(D.class);
186    assertSame(d.injector, child);
187
188    E e = child.getInstance(E.class);
189    assertSame(e.injector, parent);
190  }
191
192  public void testSeveralLayersOfHierarchy() {
193    Injector top = Guice.createInjector(bindsA);
194    Injector left = top.createChildInjector();
195    Injector leftLeft = left.createChildInjector(bindsD);
196    Injector right = top.createChildInjector(bindsD);
197    
198    assertSame(leftLeft, leftLeft.getInstance(D.class).injector);
199    assertSame(right, right.getInstance(D.class).injector);
200    assertSame(top, leftLeft.getInstance(E.class).injector);
201    assertSame(top.getInstance(A.class), leftLeft.getInstance(A.class));
202
203    Injector leftRight = left.createChildInjector(bindsD);
204    assertSame(leftRight, leftRight.getInstance(D.class).injector);
205
206    try {
207      top.getInstance(D.class);
208      fail();
209    } catch (ConfigurationException expected) {
210    }
211
212    try {
213      left.getInstance(D.class);
214      fail();
215    } catch (ConfigurationException expected) {
216    }
217  }
218
219  public void testScopeBoundInChildInjectorOnly() {
220    Injector parent = Guice.createInjector();
221    Injector child = parent.createChildInjector(new AbstractModule() {
222      @Override protected void configure() {
223        bindScope(MyScope.class, Scopes.SINGLETON);
224      }
225    });
226
227    try {
228      parent.getProvider(F.class);
229      fail();
230    } catch (ConfigurationException expected) {
231      assertContains(expected.getMessage(),
232          "No scope is bound to com.google.inject.ParentInjectorTest$MyScope.",
233          "at " + F.class.getName() + ".class(ParentInjectorTest.java",
234          "  while locating " + F.class.getName());
235    }
236    
237    assertNotNull(child.getProvider(F.class).get());
238  }
239
240  public void testErrorInParentButOkayInChild() {
241    Injector parent = Guice.createInjector();
242    Injector childInjector = parent.createChildInjector(new AbstractModule() {
243      @Override protected void configure() {
244        bindScope(MyScope.class, Scopes.SINGLETON);
245        bind(Object.class).to(F.class);
246      }
247    });
248    Object one = childInjector.getInstance(Object.class);
249    Object two = childInjector.getInstance(Object.class);
250    assertSame(one, two);
251  }
252
253  public void testErrorInParentAndChild() {
254    Injector parent = Guice.createInjector();
255    Injector childInjector = parent.createChildInjector();
256
257    try {
258      childInjector.getInstance(G.class);
259      fail();
260    } catch(ConfigurationException expected) {
261      assertContains(expected.getMessage(), "No scope is bound to " + MyScope.class.getName(),
262          "at " + F.class.getName() + ".class(ParentInjectorTest.java:",
263          "  while locating " + G.class.getName());
264    }
265  }
266
267  @Singleton
268  static class A {}
269
270  private final Module bindsA = new AbstractModule() {
271    @Override protected void configure() {
272      bind(A.class).toInstance(new A());
273    }
274  };
275
276  interface B {}
277  static class RealB implements B {}
278
279  private final Module bindsB = new AbstractModule() {
280    @Override protected void configure() {
281      bind(B.class).to(RealB.class);
282    }
283  };
284
285  @Target(TYPE) @Retention(RUNTIME) @ScopeAnnotation
286  public @interface MyScope {}
287
288  private final TypeConverter listConverter = new TypeConverter() {
289    public Object convert(String value, TypeLiteral<?> toType) {
290      return ImmutableList.of();
291    }
292  };
293
294  private final Module bindListConverterModule = new AbstractModule() {
295    @Override protected void configure() {
296      convertToTypes(Matchers.any(), listConverter);
297    }
298  };
299
300  private final Module bindStringNamedB = new AbstractModule() {
301    @Override protected void configure() {
302      bind(String.class).annotatedWith(Names.named("B")).toInstance("buzz");
303    }
304  };
305
306  public static class C {
307    public A interceptedMethod() {
308      return new A();
309    }
310  }
311
312  static class D {
313    @Inject Injector injector;
314  }
315
316  static class E {
317    @Inject Injector injector;
318  }
319
320  private final Module bindsD = new AbstractModule() {
321    @Override protected void configure() {
322      bind(D.class);
323    }
324  };
325
326  @MyScope
327  static class F implements G {}
328
329  @ImplementedBy(F.class)
330  interface G {}
331}