• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.common.collect.ImmutableSet.of;
20 import static com.google.inject.Asserts.assertContains;
21 import static com.google.inject.JitBindingsTest.GetBindingCheck.ALLOW_BINDING;
22 import static com.google.inject.JitBindingsTest.GetBindingCheck.FAIL_ALL;
23 
24 import java.util.Set;
25 import junit.framework.TestCase;
26 
27 /**
28  * Some tests for {@link Binder#requireExplicitBindings()}
29  *
30  * @author sberlin@gmail.com (Sam Berlin)
31  */
32 public class JitBindingsTest extends TestCase {
33 
jitFailed(Class<?> clazz)34   private String jitFailed(Class<?> clazz) {
35     return jitFailed(TypeLiteral.get(clazz));
36   }
37 
jitFailed(TypeLiteral<?> clazz)38   private String jitFailed(TypeLiteral<?> clazz) {
39     return "Explicit bindings are required and " + clazz + " is not explicitly bound.";
40   }
41 
jitInParentFailed(Class<?> clazz)42   private String jitInParentFailed(Class<?> clazz) {
43     return jitInParentFailed(TypeLiteral.get(clazz));
44   }
45 
jitInParentFailed(TypeLiteral<?> clazz)46   private String jitInParentFailed(TypeLiteral<?> clazz) {
47     return "Explicit bindings are required and " + clazz + " would be bound in a parent injector.";
48   }
49 
inChildMessage(Class<?> clazz)50   private String inChildMessage(Class<?> clazz) {
51     return "Unable to create binding for "
52         + clazz.getName()
53         + ". It was already configured on one or more child injectors or private modules";
54   }
55 
testLinkedBindingWorks()56   public void testLinkedBindingWorks() {
57     Injector injector =
58         Guice.createInjector(
59             new AbstractModule() {
60               @Override
61               protected void configure() {
62                 binder().requireExplicitBindings();
63                 bind(Foo.class).to(FooImpl.class);
64               }
65             });
66     // Foo was explicitly bound
67     ensureWorks(injector, Foo.class);
68     // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
69     // It is OK to call getBinding for introspection, but an error to get the provider
70     // of the binding
71     ensureFails(injector, ALLOW_BINDING, FooImpl.class);
72   }
73 
testMoreBasicsWork()74   public void testMoreBasicsWork() {
75     Injector injector =
76         Guice.createInjector(
77             new AbstractModule() {
78               @Override
79               protected void configure() {
80                 binder().requireExplicitBindings();
81                 bind(Foo.class).to(FooImpl.class);
82                 bind(Bar.class);
83                 bind(FooBar.class);
84               }
85             });
86     // Foo, Bar & FooBar was explicitly bound
87     ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
88     // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
89     // It is OK to call getBinding for introspection, but an error to get the provider
90     // of the binding
91     ensureFails(injector, ALLOW_BINDING, FooImpl.class);
92   }
93 
testLinkedEagerSingleton()94   public void testLinkedEagerSingleton() {
95     Injector injector =
96         Guice.createInjector(
97             new AbstractModule() {
98               @Override
99               protected void configure() {
100                 binder().requireExplicitBindings();
101                 bind(Foo.class).to(FooImpl.class).asEagerSingleton();
102               }
103             });
104     // Foo was explicitly bound
105     ensureWorks(injector, Foo.class);
106     // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
107     // It is OK to call getBinding for introspection, but an error to get the provider
108     // of the binding
109     ensureFails(injector, ALLOW_BINDING, FooImpl.class);
110   }
111 
testBasicsWithEagerSingleton()112   public void testBasicsWithEagerSingleton() {
113     Injector injector =
114         Guice.createInjector(
115             new AbstractModule() {
116               @Override
117               protected void configure() {
118                 binder().requireExplicitBindings();
119                 bind(Foo.class).to(FooImpl.class).asEagerSingleton();
120                 bind(Bar.class);
121                 bind(FooBar.class);
122               }
123             });
124     // Foo, Bar & FooBar was explicitly bound
125     ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
126     // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
127     // It is OK to call getBinding for introspection, but an error to get the provider
128     // of the binding
129     ensureFails(injector, ALLOW_BINDING, FooImpl.class);
130   }
131 
testLinkedToScoped()132   public void testLinkedToScoped() {
133     Injector injector =
134         Guice.createInjector(
135             new AbstractModule() {
136               @Override
137               protected void configure() {
138                 binder.requireExplicitBindings();
139                 bind(Foo.class).to(ScopedFooImpl.class);
140               }
141             });
142     // Foo was explicitly bound
143     ensureWorks(injector, Foo.class);
144     // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider,
145     // It is OK to call getBinding for introspection, but an error to get the provider
146     // of the binding
147     ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class);
148   }
149 
testBasicsWithScoped()150   public void testBasicsWithScoped() {
151     Injector injector =
152         Guice.createInjector(
153             new AbstractModule() {
154               @Override
155               protected void configure() {
156                 binder().requireExplicitBindings();
157                 bind(Foo.class).to(ScopedFooImpl.class);
158                 bind(Bar.class);
159                 bind(FooBar.class);
160               }
161             });
162     // Foo, Bar & FooBar was explicitly bound
163     ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
164     // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider,
165     // It is OK to call getBinding for introspection, but an error to get the provider
166     // of the binding
167     ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class);
168   }
169 
testFailsIfInjectingScopedDirectlyWhenItIsntBound()170   public void testFailsIfInjectingScopedDirectlyWhenItIsntBound() {
171     try {
172       Guice.createInjector(
173           new AbstractModule() {
174             @Override
175             protected void configure() {
176               binder().requireExplicitBindings();
177               bind(Foo.class).to(ScopedFooImpl.class);
178               bind(WantsScopedFooImpl.class);
179             }
180           });
181       fail();
182     } catch (CreationException expected) {
183       assertContains(expected.getMessage(), jitFailed(ScopedFooImpl.class));
184       assertEquals(1, expected.getErrorMessages().size());
185     }
186   }
187 
testLinkedProviderBindingWorks()188   public void testLinkedProviderBindingWorks() {
189     Injector injector =
190         Guice.createInjector(
191             new AbstractModule() {
192               @Override
193               protected void configure() {
194                 binder().requireExplicitBindings();
195                 bind(Foo.class).toProvider(FooProvider.class);
196               }
197             });
198     // Foo was explicitly bound
199     ensureWorks(injector, Foo.class);
200     // FooImpl was not bound at all (even implicitly), it is an error
201     // to call getInstance, getProvider, or getBinding.
202     ensureFails(injector, FAIL_ALL, FooImpl.class);
203   }
204 
testJitGetFails()205   public void testJitGetFails() {
206     try {
207       Guice.createInjector(
208               new AbstractModule() {
209                 @Override
210                 protected void configure() {
211                   binder().requireExplicitBindings();
212                 }
213               })
214           .getInstance(Bar.class);
215       fail("should have failed");
216     } catch (ConfigurationException expected) {
217       assertContains(expected.getMessage(), jitFailed(Bar.class));
218       assertEquals(1, expected.getErrorMessages().size());
219     }
220   }
221 
testJitInjectionFails()222   public void testJitInjectionFails() {
223     try {
224       Guice.createInjector(
225           new AbstractModule() {
226             @Override
227             protected void configure() {
228               binder().requireExplicitBindings();
229               bind(Foo.class).to(FooImpl.class);
230               bind(FooBar.class);
231             }
232           });
233       fail("should have failed");
234     } catch (CreationException expected) {
235       assertContains(expected.getMessage(), jitFailed(Bar.class));
236       assertEquals(1, expected.getErrorMessages().size());
237     }
238   }
239 
testJitProviderGetFails()240   public void testJitProviderGetFails() {
241     try {
242       Guice.createInjector(
243               new AbstractModule() {
244                 @Override
245                 protected void configure() {
246                   binder().requireExplicitBindings();
247                 }
248               })
249           .getProvider(Bar.class);
250       fail("should have failed");
251     } catch (ConfigurationException expected) {
252       assertContains(expected.getMessage(), jitFailed(Bar.class));
253       assertEquals(1, expected.getErrorMessages().size());
254     }
255   }
256 
testJitProviderInjectionFails()257   public void testJitProviderInjectionFails() {
258     try {
259       Guice.createInjector(
260           new AbstractModule() {
261             @Override
262             protected void configure() {
263               binder().requireExplicitBindings();
264               bind(Foo.class).to(FooImpl.class);
265               bind(ProviderFooBar.class);
266             }
267           });
268       fail("should have failed");
269     } catch (CreationException expected) {
270       assertContains(expected.getMessage(), jitFailed(Bar.class));
271       assertEquals(1, expected.getErrorMessages().size());
272     }
273   }
274 
testImplementedBy()275   public void testImplementedBy() {
276     Injector injector =
277         Guice.createInjector(
278             new AbstractModule() {
279               @Override
280               protected void configure() {
281                 binder().requireExplicitBindings();
282                 bind(ImplBy.class);
283               }
284             });
285     ensureWorks(injector, ImplBy.class);
286     ensureFails(injector, ALLOW_BINDING, ImplByImpl.class);
287   }
288 
testImplementedBySomethingThatIsAnnotated()289   public void testImplementedBySomethingThatIsAnnotated() {
290     Injector injector =
291         Guice.createInjector(
292             new AbstractModule() {
293               @Override
294               protected void configure() {
295                 binder().requireExplicitBindings();
296                 bind(ImplByScoped.class);
297               }
298             });
299     ensureWorks(injector, ImplByScoped.class);
300     ensureFails(injector, ALLOW_BINDING, ImplByScopedImpl.class);
301   }
302 
testProvidedBy()303   public void testProvidedBy() {
304     Injector injector =
305         Guice.createInjector(
306             new AbstractModule() {
307               @Override
308               protected void configure() {
309                 binder().requireExplicitBindings();
310                 bind(ProvBy.class);
311               }
312             });
313     ensureWorks(injector, ProvBy.class);
314     ensureFails(injector, ALLOW_BINDING, ProvByProvider.class);
315   }
316 
testProviderMethods()317   public void testProviderMethods() {
318     Injector injector =
319         Guice.createInjector(
320             new AbstractModule() {
321               @Override
322               protected void configure() {
323                 binder().requireExplicitBindings();
324               }
325 
326               @SuppressWarnings("unused")
327               @Provides
328               Foo foo() {
329                 return new FooImpl();
330               }
331             });
332     ensureWorks(injector, Foo.class);
333   }
334 
testChildInjectorInheritsOption()335   public void testChildInjectorInheritsOption() {
336     Injector parent =
337         Guice.createInjector(
338             new AbstractModule() {
339               @Override
340               protected void configure() {
341                 binder().requireExplicitBindings();
342                 bind(Bar.class);
343               }
344             });
345     ensureWorks(parent, Bar.class);
346     ensureFails(parent, FAIL_ALL, FooImpl.class, FooBar.class, Foo.class);
347 
348     try {
349       parent.createChildInjector(
350           new AbstractModule() {
351             @Override
352             protected void configure() {
353               bind(FooBar.class);
354             }
355           });
356       fail("should have failed");
357     } catch (CreationException expected) {
358       assertContains(expected.getMessage(), jitFailed(Foo.class));
359       assertEquals(1, expected.getErrorMessages().size());
360     }
361 
362     Injector child =
363         parent.createChildInjector(
364             new AbstractModule() {
365               @Override
366               protected void configure() {
367                 bind(Foo.class).to(FooImpl.class);
368               }
369             });
370     ensureWorks(child, Foo.class, Bar.class);
371     ensureFails(child, ALLOW_BINDING, FooImpl.class);
372     ensureInChild(parent, FooImpl.class, Foo.class);
373     // TODO(sameb): FooBar may or may not be in a child injector, depending on if GC has run.
374     // We should fix failed child injectors to remove their contents from the parent blacklist
375     // immediately, rather than waiting on GC to do it.
376     // FooBar was succesfully inserted into the child injector (and parent blacklist), but then
377     // JIT bindings it depended on failed, making the child injector invalid.
378 
379     Injector grandchild =
380         child.createChildInjector(
381             new AbstractModule() {
382               @Override
383               protected void configure() {
384                 bind(FooBar.class);
385               }
386             });
387     ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class);
388     ensureFails(grandchild, ALLOW_BINDING, FooImpl.class);
389     ensureFails(child, ALLOW_BINDING, FooImpl.class);
390     ensureInChild(parent, FooImpl.class, FooBar.class, Foo.class);
391   }
392 
testChildInjectorAddsOption()393   public void testChildInjectorAddsOption() {
394     Injector parent =
395         Guice.createInjector(
396             new AbstractModule() {
397               @Override
398               protected void configure() {
399                 bind(Bar.class);
400               }
401             });
402     int totalParentBindings = parent.getAllBindings().size();
403 
404     try {
405       parent.createChildInjector(
406           new AbstractModule() {
407             @Override
408             protected void configure() {
409               binder().requireExplicitBindings();
410               bind(FooBar.class);
411             }
412           });
413       fail("should have failed");
414     } catch (CreationException expected) {
415       assertContains(expected.getMessage(), jitFailed(Foo.class));
416       assertEquals(1, expected.getErrorMessages().size());
417     }
418     assertEquals(totalParentBindings, parent.getAllBindings().size());
419 
420     Injector child =
421         parent.createChildInjector(
422             new AbstractModule() {
423               @Override
424               protected void configure() {
425                 binder().requireExplicitBindings();
426                 bind(Foo.class).to(FooImpl.class);
427                 bind(FooImpl.class);
428               }
429             });
430     assertEquals(totalParentBindings, parent.getAllBindings().size());
431     ensureWorks(child, Foo.class, Bar.class);
432 
433     Injector grandchild =
434         child.createChildInjector(
435             new AbstractModule() {
436               @Override
437               protected void configure() {
438                 bind(FooBar.class);
439               }
440             });
441     assertEquals(totalParentBindings, parent.getAllBindings().size());
442     ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class);
443 
444     // Make sure siblings of children don't inherit each others settings...
445     // a new child should be able to get FooImpl.
446     child = parent.createChildInjector();
447     ensureWorks(child, FooImpl.class);
448   }
449 
testPrivateModulesInheritOptions()450   public void testPrivateModulesInheritOptions() {
451     try {
452       Guice.createInjector(
453           new AbstractModule() {
454             @Override
455             protected void configure() {
456               binder().requireExplicitBindings();
457               bind(Foo.class).to(FooImpl.class);
458 
459               install(
460                   new PrivateModule() {
461                     @Override
462                     public void configure() {
463                       bind(FooBar.class);
464                       expose(FooBar.class);
465                     }
466                   });
467             }
468           });
469       fail("should have failed");
470     } catch (CreationException expected) {
471       assertContains(expected.getMessage(), jitFailed(Bar.class));
472       assertEquals(1, expected.getErrorMessages().size());
473     }
474 
475     Injector injector =
476         Guice.createInjector(
477             new AbstractModule() {
478               @Override
479               protected void configure() {
480                 binder().requireExplicitBindings();
481 
482                 install(
483                     new PrivateModule() {
484                       @Override
485                       public void configure() {
486                         bind(Foo.class).to(FooImpl.class);
487                         expose(Foo.class);
488                       }
489                     });
490               }
491             });
492     ensureInChild(injector, FooImpl.class);
493   }
494 
testPrivateModuleAddsOption()495   public void testPrivateModuleAddsOption() {
496     try {
497       Guice.createInjector(
498           new AbstractModule() {
499             @Override
500             protected void configure() {
501               bind(Foo.class).to(FooImpl.class);
502 
503               // Fails because FooBar is in the private module,
504               // and it wants Bar, but Bar would be JIT.
505               install(
506                   new PrivateModule() {
507                     @Override
508                     public void configure() {
509                       binder().requireExplicitBindings();
510                       bind(FooBar.class);
511                       expose(FooBar.class);
512                     }
513                   });
514             }
515           });
516       fail("should have failed");
517     } catch (CreationException expected) {
518       assertContains(expected.getMessage(), jitFailed(Bar.class));
519       assertEquals(1, expected.getErrorMessages().size());
520     }
521   }
522 
testPrivateModuleSiblingsDontShareOption()523   public void testPrivateModuleSiblingsDontShareOption() {
524     Guice.createInjector(
525         new AbstractModule() {
526           @Override
527           protected void configure() {
528             bind(Foo.class).to(FooImpl.class);
529 
530             install(
531                 new PrivateModule() {
532                   @Override
533                   public void configure() {
534                     binder().requireExplicitBindings();
535                   }
536                 });
537 
538             // This works, even though Bar is JIT,
539             // because the requireExplicitBindings isn't shared
540             // between sibling private modules.
541             install(
542                 new PrivateModule() {
543                   @Override
544                   public void configure() {
545                     bind(FooBar.class);
546                     expose(FooBar.class);
547                   }
548                 });
549           }
550         });
551   }
552 
testTypeLiteralsCanBeInjected()553   public void testTypeLiteralsCanBeInjected() {
554     Injector injector =
555         Guice.createInjector(
556             new AbstractModule() {
557               @Override
558               protected void configure() {
559                 binder().requireExplicitBindings();
560                 bind(new TypeLiteral<WantsTypeLiterals<String>>() {});
561                 bind(new TypeLiteral<Set<String>>() {}).toInstance(of("bar"));
562               }
563             });
564 
565     WantsTypeLiterals<String> foo = injector.getInstance(new Key<WantsTypeLiterals<String>>() {});
566     assertEquals(foo.literal.getRawType(), String.class);
567     assertEquals(of("bar"), foo.set);
568   }
569 
testMembersInjectorsCanBeInjected()570   public void testMembersInjectorsCanBeInjected() {
571     Injector injector =
572         Guice.createInjector(
573             new AbstractModule() {
574               @Override
575               protected void configure() {
576                 binder().requireExplicitBindings();
577               }
578 
579               @Provides
580               String data(MembersInjector<String> mi) {
581                 String data = "foo";
582                 mi.injectMembers(data);
583                 return data;
584               }
585             });
586 
587     String data = injector.getInstance(String.class);
588     assertEquals("foo", data);
589   }
590 
testJitLinkedBindingInParentFails()591   public void testJitLinkedBindingInParentFails() {
592     try {
593       Guice.createInjector(
594           new AbstractModule() {
595             @Override
596             protected void configure() {
597               install(
598                   new PrivateModule() {
599                     @Override
600                     protected void configure() {
601                       binder().requireExplicitBindings();
602                       bind(Foo.class).to(FooImpl.class);
603                     }
604                   });
605             }
606           });
607       fail("should have failed");
608     } catch (CreationException expected) {
609       assertContains(expected.getMessage(), jitInParentFailed(FooImpl.class));
610       assertEquals(1, expected.getErrorMessages().size());
611     }
612   }
613 
testJitProviderBindingInParentFails()614   public void testJitProviderBindingInParentFails() {
615     try {
616       Guice.createInjector(
617           new AbstractModule() {
618             @Override
619             protected void configure() {
620               install(
621                   new PrivateModule() {
622                     @Override
623                     protected void configure() {
624                       binder().requireExplicitBindings();
625                       bind(Foo.class).toProvider(FooProvider.class);
626                     }
627                   });
628             }
629           });
630       fail("should have failed");
631     } catch (CreationException expected) {
632       assertContains(expected.getMessage(), jitInParentFailed(FooProvider.class));
633       assertEquals(1, expected.getErrorMessages().size());
634     }
635   }
636 
testJitImplementedByBindingInParentFails()637   public void testJitImplementedByBindingInParentFails() {
638     try {
639       Guice.createInjector(
640           new AbstractModule() {
641             @Override
642             protected void configure() {
643               install(
644                   new PrivateModule() {
645                     @Override
646                     protected void configure() {
647                       binder().requireExplicitBindings();
648                       bind(ImplBy.class);
649                     }
650                   });
651             }
652           });
653       fail("should have failed");
654     } catch (CreationException expected) {
655       assertContains(expected.getMessage(), jitInParentFailed(ImplByImpl.class));
656       assertEquals(1, expected.getErrorMessages().size());
657     }
658   }
659 
testJitProvidedByBindingInParentFails()660   public void testJitProvidedByBindingInParentFails() {
661     try {
662       Guice.createInjector(
663           new AbstractModule() {
664             @Override
665             protected void configure() {
666               install(
667                   new PrivateModule() {
668                     @Override
669                     protected void configure() {
670                       binder().requireExplicitBindings();
671                       bind(ProvBy.class);
672                     }
673                   });
674             }
675           });
676       fail("should have failed");
677     } catch (CreationException expected) {
678       assertContains(expected.getMessage(), jitInParentFailed(ProvByProvider.class));
679       assertEquals(1, expected.getErrorMessages().size());
680     }
681   }
682 
ensureWorks(Injector injector, Class<?>... classes)683   private void ensureWorks(Injector injector, Class<?>... classes) {
684     for (int i = 0; i < classes.length; i++) {
685       injector.getInstance(classes[i]);
686       injector.getProvider(classes[i]).get();
687       injector.getBinding(classes[i]).getProvider().get();
688     }
689   }
690 
691   enum GetBindingCheck {
692     FAIL_ALL,
693     ALLOW_BINDING,
694     ALLOW_BINDING_PROVIDER
695   }
696 
ensureFails(Injector injector, GetBindingCheck getBinding, Class<?>... classes)697   private void ensureFails(Injector injector, GetBindingCheck getBinding, Class<?>... classes) {
698     for (int i = 0; i < classes.length; i++) {
699       try {
700         injector.getInstance(classes[i]);
701         fail("should have failed tring to retrieve class: " + classes[i]);
702       } catch (ConfigurationException expected) {
703         assertContains(expected.getMessage(), jitFailed(classes[i]));
704         assertEquals(1, expected.getErrorMessages().size());
705       }
706 
707       try {
708         injector.getProvider(classes[i]);
709         fail("should have failed tring to retrieve class: " + classes[i]);
710       } catch (ConfigurationException expected) {
711         assertContains(expected.getMessage(), jitFailed(classes[i]));
712         assertEquals(1, expected.getErrorMessages().size());
713       }
714 
715       if (getBinding == GetBindingCheck.ALLOW_BINDING
716           || getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) {
717         Binding<?> binding = injector.getBinding(classes[i]);
718         try {
719           binding.getProvider();
720           if (getBinding != GetBindingCheck.ALLOW_BINDING_PROVIDER) {
721             fail("should have failed trying to retrieve class: " + classes[i]);
722           }
723         } catch (ConfigurationException expected) {
724           if (getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) {
725             throw expected;
726           }
727           assertContains(expected.getMessage(), jitFailed(classes[i]));
728           assertEquals(1, expected.getErrorMessages().size());
729         }
730       } else {
731         try {
732           injector.getBinding(classes[i]);
733           fail("should have failed tring to retrieve class: " + classes[i]);
734         } catch (ConfigurationException expected) {
735           assertContains(expected.getMessage(), jitFailed(classes[i]));
736           assertEquals(1, expected.getErrorMessages().size());
737         }
738       }
739     }
740   }
741 
ensureInChild(Injector injector, Class<?>... classes)742   private void ensureInChild(Injector injector, Class<?>... classes) {
743     for (int i = 0; i < classes.length; i++) {
744       try {
745         injector.getInstance(classes[i]);
746         fail("should have failed tring to retrieve class: " + classes[i]);
747       } catch (ConfigurationException expected) {
748         assertContains(expected.getMessage(), inChildMessage(classes[i]));
749         assertEquals(1, expected.getErrorMessages().size());
750       }
751 
752       try {
753         injector.getProvider(classes[i]);
754         fail("should have failed tring to retrieve class: " + classes[i]);
755       } catch (ConfigurationException expected) {
756         assertContains(expected.getMessage(), inChildMessage(classes[i]));
757         assertEquals(1, expected.getErrorMessages().size());
758       }
759 
760       try {
761         injector.getBinding(classes[i]);
762         fail("should have failed tring to retrieve class: " + classes[i]);
763       } catch (ConfigurationException expected) {
764         assertContains(expected.getMessage(), inChildMessage(classes[i]));
765         assertEquals(1, expected.getErrorMessages().size());
766       }
767     }
768   }
769 
770   private static interface Foo {}
771 
772   private static class FooImpl implements Foo {}
773 
774   @Singleton
775   private static class ScopedFooImpl implements Foo {}
776 
777   private static class WantsScopedFooImpl {
778     @SuppressWarnings("unused")
779     @Inject
780     ScopedFooImpl scopedFoo;
781   }
782 
783   private static class Bar {}
784 
785   private static class FooBar {
786     @SuppressWarnings("unused")
787     @Inject
788     Foo foo;
789 
790     @SuppressWarnings("unused")
791     @Inject
792     Bar bar;
793   }
794 
795   private static class ProviderFooBar {
796     @SuppressWarnings("unused")
797     @Inject
798     Provider<Foo> foo;
799 
800     @SuppressWarnings("unused")
801     @Inject
802     Provider<Bar> bar;
803   }
804 
805   private static class FooProvider implements Provider<Foo> {
806     @Override
get()807     public Foo get() {
808       return new FooImpl();
809     }
810   }
811 
812   @ImplementedBy(ImplByImpl.class)
813   private static interface ImplBy {}
814 
815   private static class ImplByImpl implements ImplBy {}
816 
817   @ImplementedBy(ImplByScopedImpl.class)
818   private static interface ImplByScoped {}
819 
820   @Singleton
821   private static class ImplByScopedImpl implements ImplByScoped {}
822 
823   @ProvidedBy(ProvByProvider.class)
824   private static interface ProvBy {}
825 
826   private static class ProvByProvider implements Provider<ProvBy> {
827     @Override
get()828     public ProvBy get() {
829       return new ProvBy() {};
830     }
831   }
832 
833   private static class WantsTypeLiterals<T> {
834     TypeLiteral<T> literal;
835     Set<T> set;
836 
837     @Inject
WantsTypeLiterals(TypeLiteral<T> literal, Set<T> set)838     WantsTypeLiterals(TypeLiteral<T> literal, Set<T> set) {
839       this.literal = literal;
840       this.set = set;
841     }
842   }
843 }
844