• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.Asserts.asModuleChain;
20 import static com.google.inject.Asserts.assertContains;
21 import static com.google.inject.Asserts.assertNotSerializable;
22 import static com.google.inject.Asserts.getDeclaringSourcePart;
23 
24 import com.google.common.collect.Iterables;
25 import com.google.common.collect.Lists;
26 import com.google.inject.internal.Annotations;
27 import com.google.inject.name.Named;
28 import com.google.inject.name.Names;
29 import com.google.inject.spi.Message;
30 import com.google.inject.util.Providers;
31 import java.io.IOException;
32 import java.util.Comparator;
33 import java.util.Date;
34 import java.util.List;
35 import java.util.concurrent.Callable;
36 import java.util.logging.Handler;
37 import java.util.logging.LogRecord;
38 import java.util.logging.Logger;
39 import junit.framework.TestCase;
40 
41 /** @author crazybob@google.com (Bob Lee) */
42 public class BinderTest extends TestCase {
43 
44   private final Logger loggerToWatch = Logger.getLogger(Guice.class.getName());
45 
46   private final List<LogRecord> logRecords = Lists.newArrayList();
47   private final Handler fakeHandler =
48       new Handler() {
49         @Override
50         public void publish(LogRecord logRecord) {
51           logRecords.add(logRecord);
52         }
53 
54         @Override
55         public void flush() {}
56 
57         @Override
58         public void close() throws SecurityException {}
59       };
60 
61   Provider<Foo> fooProvider;
62 
63   @Override
setUp()64   protected void setUp() throws Exception {
65     super.setUp();
66     loggerToWatch.addHandler(fakeHandler);
67   }
68 
69   @Override
tearDown()70   protected void tearDown() throws Exception {
71     loggerToWatch.removeHandler(fakeHandler);
72     super.tearDown();
73   }
74 
testProviderFromBinder()75   public void testProviderFromBinder() {
76     Guice.createInjector(
77         new Module() {
78           @Override
79           public void configure(Binder binder) {
80             fooProvider = binder.getProvider(Foo.class);
81 
82             try {
83               fooProvider.get();
84               fail();
85             } catch (IllegalStateException e) {
86               /* expected */
87             }
88           }
89         });
90 
91     assertNotNull(fooProvider.get());
92   }
93 
94   static class Foo {}
95 
testMissingBindings()96   public void testMissingBindings() {
97     try {
98       Guice.createInjector(
99           // We put each binding in a separate module so the order of the error messages doesn't
100           // depend on line numbers
101           new AbstractModule() {
102             @Override
103             public void configure() {
104               getProvider(Runnable.class);
105             }
106           },
107           new AbstractModule() {
108             @Override
109             public void configure() {
110               bind(Comparator.class);
111             }
112           },
113           new AbstractModule() {
114             @Override
115             public void configure() {
116               requireBinding(Key.get(new TypeLiteral<Callable<String>>() {}));
117             }
118           },
119           new AbstractModule() {
120             @Override
121             public void configure() {
122               bind(Date.class).annotatedWith(Names.named("date"));
123             }
124           });
125       fail("Expected CreationException");
126     } catch (CreationException e) {
127       assertEquals(4, e.getErrorMessages().size());
128       String segment1 = "No implementation for java.lang.Runnable was bound.";
129       String segment2 = "No implementation for " + Comparator.class.getName() + " was bound.";
130       String segment3 =
131           "No implementation for java.util.concurrent.Callable<java.lang.String> was" + " bound.";
132       String segment4 =
133           "No implementation for java.util.Date annotated with @"
134               + Named.class.getName()
135               + "(value="
136               + Annotations.memberValueString("date")
137               + ") was bound.";
138       String atSegment = "at " + getClass().getName();
139       String sourceFileName = getDeclaringSourcePart(getClass());
140       assertContains(
141           e.getMessage(),
142           segment1,
143           atSegment,
144           sourceFileName,
145           segment2,
146           atSegment,
147           sourceFileName,
148           segment3,
149           atSegment,
150           sourceFileName,
151           segment4,
152           atSegment,
153           sourceFileName);
154     }
155   }
156 
testMissingDependency()157   public void testMissingDependency() {
158     try {
159       Guice.createInjector(
160           new AbstractModule() {
161             @Override
162             public void configure() {
163               bind(NeedsRunnable.class);
164             }
165           });
166       fail("Expected CreationException");
167     } catch (CreationException e) {
168       assertEquals(1, e.getErrorMessages().size());
169       assertContains(
170           e.getMessage(),
171           "No implementation for java.lang.Runnable was bound.",
172           "for field at " + NeedsRunnable.class.getName(),
173           ".runnable(BinderTest.java:",
174           "at " + getClass().getName(),
175           getDeclaringSourcePart(getClass()));
176     }
177   }
178 
179   static class NeedsRunnable {
180     @Inject Runnable runnable;
181   }
182 
testDanglingConstantBinding()183   public void testDanglingConstantBinding() {
184     try {
185       Guice.createInjector(
186           new AbstractModule() {
187             @Override
188             public void configure() {
189               bindConstant();
190             }
191           });
192       fail();
193     } catch (CreationException expected) {
194       assertContains(
195           expected.getMessage(),
196           "1) Missing constant value. Please call to(...).",
197           "at " + getClass().getName());
198     }
199   }
200 
testRecursiveBinding()201   public void testRecursiveBinding() {
202     try {
203       Guice.createInjector(
204           new AbstractModule() {
205             @Override
206             public void configure() {
207               bind(Runnable.class).to(Runnable.class);
208             }
209           });
210       fail();
211     } catch (CreationException expected) {
212       assertContains(
213           expected.getMessage(),
214           "1) Binding points to itself.",
215           "at " + getClass().getName(),
216           getDeclaringSourcePart(getClass()));
217     }
218   }
219 
testBindingNullConstant()220   public void testBindingNullConstant() {
221     try {
222       Guice.createInjector(
223           new AbstractModule() {
224             @Override
225             public void configure() {
226               String none = null;
227               bindConstant().annotatedWith(Names.named("nullOne")).to(none);
228               bind(String.class).annotatedWith(Names.named("nullTwo")).toInstance(none);
229             }
230           });
231       fail();
232     } catch (CreationException expected) {
233       assertContains(
234           expected.getMessage(),
235           "1) Binding to null instances is not allowed. Use toProvider(Providers.of(null))",
236           "2) Binding to null instances is not allowed. Use toProvider(Providers.of(null))");
237     }
238   }
239 
testToStringOnBinderApi()240   public void testToStringOnBinderApi() {
241     try {
242       Guice.createInjector(
243           new AbstractModule() {
244             @Override
245             public void configure() {
246               assertEquals("Binder", binder().toString());
247               assertEquals("Provider<java.lang.Integer>", getProvider(Integer.class).toString());
248               assertEquals(
249                   "Provider<java.util.List<java.lang.String>>",
250                   getProvider(Key.get(new TypeLiteral<List<String>>() {})).toString());
251 
252               assertEquals("BindingBuilder<java.lang.Integer>", bind(Integer.class).toString());
253               assertEquals(
254                   "BindingBuilder<java.lang.Integer>",
255                   bind(Integer.class).annotatedWith(Names.named("a")).toString());
256               assertEquals("ConstantBindingBuilder", bindConstant().toString());
257               assertEquals(
258                   "ConstantBindingBuilder",
259                   bindConstant().annotatedWith(Names.named("b")).toString());
260               assertEquals(
261                   "AnnotatedElementBuilder",
262                   binder().newPrivateBinder().expose(Integer.class).toString());
263             }
264           });
265       fail();
266     } catch (CreationException ignored) {
267     }
268   }
269 
testNothingIsSerializableInBinderApi()270   public void testNothingIsSerializableInBinderApi() {
271     try {
272       Guice.createInjector(
273           new AbstractModule() {
274             @Override
275             public void configure() {
276               try {
277                 assertNotSerializable(binder());
278                 assertNotSerializable(getProvider(Integer.class));
279                 assertNotSerializable(getProvider(Key.get(new TypeLiteral<List<String>>() {})));
280                 assertNotSerializable(bind(Integer.class));
281                 assertNotSerializable(bind(Integer.class).annotatedWith(Names.named("a")));
282                 assertNotSerializable(bindConstant());
283                 assertNotSerializable(bindConstant().annotatedWith(Names.named("b")));
284               } catch (IOException e) {
285                 fail(e.getMessage());
286               }
287             }
288           });
289       fail();
290     } catch (CreationException ignored) {
291     }
292   }
293 
294   /**
295    * Although {@code String[].class} isn't equal to {@code new GenericArrayTypeImpl(String.class)},
296    * Guice should treat these two types interchangeably.
297    */
testArrayTypeCanonicalization()298   public void testArrayTypeCanonicalization() {
299     final String[] strings = new String[] {"A"};
300     final Integer[] integers = new Integer[] {1};
301 
302     Injector injector =
303         Guice.createInjector(
304             new AbstractModule() {
305               @Override
306               protected void configure() {
307                 bind(String[].class).toInstance(strings);
308                 bind(new TypeLiteral<Integer[]>() {}).toInstance(integers);
309               }
310             });
311 
312     assertSame(integers, injector.getInstance(Key.get(new TypeLiteral<Integer[]>() {})));
313     assertSame(integers, injector.getInstance(new Key<Integer[]>() {}));
314     assertSame(integers, injector.getInstance(Integer[].class));
315     assertSame(strings, injector.getInstance(Key.get(new TypeLiteral<String[]>() {})));
316     assertSame(strings, injector.getInstance(new Key<String[]>() {}));
317     assertSame(strings, injector.getInstance(String[].class));
318 
319     try {
320       Guice.createInjector(
321           new AbstractModule() {
322             @Override
323             protected void configure() {
324               bind(String[].class).toInstance(new String[] {"A"});
325               bind(new TypeLiteral<String[]>() {}).toInstance(new String[] {"B"});
326             }
327           });
328       fail();
329     } catch (CreationException expected) {
330       assertContains(
331           expected.getMessage(),
332           "1) A binding to java.lang.String[] was already configured at " + getClass().getName(),
333           "at " + getClass().getName(),
334           getDeclaringSourcePart(getClass()));
335       assertContains(expected.getMessage(), "1 error");
336     }
337 
338     // passes because duplicates are ignored
339     injector =
340         Guice.createInjector(
341             new AbstractModule() {
342               @Override
343               protected void configure() {
344                 bind(String[].class).toInstance(strings);
345                 bind(new TypeLiteral<String[]>() {}).toInstance(strings);
346               }
347             });
348     assertSame(strings, injector.getInstance(Key.get(new TypeLiteral<String[]>() {})));
349     assertSame(strings, injector.getInstance(new Key<String[]>() {}));
350     assertSame(strings, injector.getInstance(String[].class));
351   }
352 
353   static class ParentModule extends AbstractModule {
354     @Override
configure()355     protected void configure() {
356       install(new FooModule());
357       install(new BarModule());
358     }
359   }
360 
361   static class FooModule extends AbstractModule {
362     @Override
configure()363     protected void configure() {
364       install(new ConstantModule("foo"));
365     }
366   }
367 
368   static class BarModule extends AbstractModule {
369     @Override
configure()370     protected void configure() {
371       install(new ConstantModule("bar"));
372     }
373   }
374 
375   static class ConstantModule extends AbstractModule {
376     private final String constant;
377 
ConstantModule(String constant)378     ConstantModule(String constant) {
379       this.constant = constant;
380     }
381 
382     @Override
configure()383     protected void configure() {
384       bind(String.class).toInstance(constant);
385     }
386   }
387 
388   /** Binding something to two different things should give an error. */
testSettingBindingTwice()389   public void testSettingBindingTwice() {
390     try {
391       Guice.createInjector(new ParentModule());
392       fail();
393     } catch (CreationException expected) {
394       assertContains(
395           expected.getMessage(),
396           "1) A binding to java.lang.String was already configured at "
397               + ConstantModule.class.getName(),
398           asModuleChain(ParentModule.class, FooModule.class, ConstantModule.class),
399           "at " + ConstantModule.class.getName(),
400           getDeclaringSourcePart(getClass()),
401           asModuleChain(ParentModule.class, BarModule.class, ConstantModule.class));
402       assertContains(expected.getMessage(), "1 error");
403     }
404   }
405 
406   /** Binding an @ImplementedBy thing to something else should also fail. */
testSettingAtImplementedByTwice()407   public void testSettingAtImplementedByTwice() {
408     try {
409       Guice.createInjector(
410           new AbstractModule() {
411             @Override
412             protected void configure() {
413               bind(HasImplementedBy1.class);
414               bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {});
415             }
416           });
417       fail();
418     } catch (CreationException expected) {
419       expected.printStackTrace();
420       assertContains(
421           expected.getMessage(),
422           "1) A binding to "
423               + HasImplementedBy1.class.getName()
424               + " was already configured at "
425               + getClass().getName(),
426           "at " + getClass().getName(),
427           getDeclaringSourcePart(getClass()));
428       assertContains(expected.getMessage(), "1 error");
429     }
430   }
431 
432   /** See issue 614, Problem One https://github.com/google/guice/issues/614 */
testJitDependencyDoesntBlockOtherExplicitBindings()433   public void testJitDependencyDoesntBlockOtherExplicitBindings() {
434     Injector injector =
435         Guice.createInjector(
436             new AbstractModule() {
437               @Override
438               protected void configure() {
439                 bind(HasImplementedByThatNeedsAnotherImplementedBy.class);
440                 bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {});
441               }
442             });
443     injector.getAllBindings(); // just validate it doesn't throw.
444     // Also validate that we're using the explicit (and not @ImplementedBy) implementation
445     assertFalse(
446         injector.getInstance(HasImplementedBy1.class) instanceof ImplementsHasImplementedBy1);
447   }
448 
449   /** See issue 614, Problem Two https://github.com/google/guice/issues/id=614 */
testJitDependencyCanUseExplicitDependencies()450   public void testJitDependencyCanUseExplicitDependencies() {
451     Guice.createInjector(
452         new AbstractModule() {
453           @Override
454           protected void configure() {
455             bind(HasImplementedByThatWantsExplicit.class);
456             bind(JustAnInterface.class).toInstance(new JustAnInterface() {});
457           }
458         });
459   }
460 
461   /**
462    * Untargetted bindings should follow @ImplementedBy and @ProvidedBy annotations if they exist.
463    * Otherwise the class should be constructed directly.
464    */
testUntargettedBinding()465   public void testUntargettedBinding() {
466     Injector injector =
467         Guice.createInjector(
468             new AbstractModule() {
469               @Override
470               protected void configure() {
471                 bind(HasProvidedBy1.class);
472                 bind(HasImplementedBy1.class);
473                 bind(HasProvidedBy2.class);
474                 bind(HasImplementedBy2.class);
475                 bind(JustAClass.class);
476               }
477             });
478 
479     assertNotNull(injector.getInstance(HasProvidedBy1.class));
480     assertNotNull(injector.getInstance(HasImplementedBy1.class));
481     assertNotSame(HasProvidedBy2.class, injector.getInstance(HasProvidedBy2.class).getClass());
482     assertSame(
483         ExtendsHasImplementedBy2.class, injector.getInstance(HasImplementedBy2.class).getClass());
484     assertSame(JustAClass.class, injector.getInstance(JustAClass.class).getClass());
485   }
486 
testPartialInjectorGetInstance()487   public void testPartialInjectorGetInstance() {
488     Injector injector = Guice.createInjector();
489     try {
490       injector.getInstance(MissingParameter.class);
491       fail();
492     } catch (ConfigurationException expected) {
493       assertContains(
494           expected.getMessage(),
495           "1) Could not find a suitable constructor in " + NoInjectConstructor.class.getName(),
496           "for the 1st parameter of "
497               + MissingParameter.class.getName()
498               + ".<init>(BinderTest.java:");
499     }
500   }
501 
testUserReportedError()502   public void testUserReportedError() {
503     final Message message = new Message(getClass(), "Whoops!");
504     try {
505       Guice.createInjector(
506           new AbstractModule() {
507             @Override
508             protected void configure() {
509               addError(message);
510             }
511           });
512       fail();
513     } catch (CreationException expected) {
514       assertSame(message, Iterables.getOnlyElement(expected.getErrorMessages()));
515     }
516   }
517 
testUserReportedErrorsAreAlsoLogged()518   public void testUserReportedErrorsAreAlsoLogged() {
519     try {
520       Guice.createInjector(
521           new AbstractModule() {
522             @Override
523             protected void configure() {
524               addError(new Message("Whoops!", new IllegalArgumentException()));
525             }
526           });
527       fail();
528     } catch (CreationException expected) {
529     }
530 
531     LogRecord logRecord = Iterables.getOnlyElement(this.logRecords);
532     assertContains(
533         logRecord.getMessage(),
534         "An exception was caught and reported. Message: java.lang.IllegalArgumentException");
535   }
536 
testBindingToProvider()537   public void testBindingToProvider() {
538     try {
539       Guice.createInjector(
540           new AbstractModule() {
541             @Override
542             protected void configure() {
543               bind(new TypeLiteral<Provider<String>>() {}).toInstance(Providers.of("A"));
544             }
545           });
546       fail();
547     } catch (CreationException expected) {
548       assertContains(
549           expected.getMessage(),
550           "1) Binding to Provider is not allowed.",
551           "at " + BinderTest.class.getName(),
552           getDeclaringSourcePart(getClass()));
553     }
554   }
555 
556   static class OuterCoreModule extends AbstractModule {
557     @Override
configure()558     protected void configure() {
559       install(new InnerCoreModule());
560     }
561   }
562 
563   static class InnerCoreModule extends AbstractModule {
564     final Named red = Names.named("red");
565 
566     @Override
configure()567     protected void configure() {
568       bind(AbstractModule.class).annotatedWith(red).toProvider(Providers.<AbstractModule>of(null));
569       bind(Binder.class).annotatedWith(red).toProvider(Providers.<Binder>of(null));
570       bind(Binding.class).annotatedWith(red).toProvider(Providers.<Binding>of(null));
571       bind(Injector.class).annotatedWith(red).toProvider(Providers.<Injector>of(null));
572       bind(Key.class).annotatedWith(red).toProvider(Providers.<Key>of(null));
573       bind(Module.class).annotatedWith(red).toProvider(Providers.<Module>of(null));
574       bind(Provider.class).annotatedWith(red).toProvider(Providers.<Provider>of(null));
575       bind(Scope.class).annotatedWith(red).toProvider(Providers.<Scope>of(null));
576       bind(Stage.class).annotatedWith(red).toProvider(Providers.<Stage>of(null));
577       bind(TypeLiteral.class).annotatedWith(red).toProvider(Providers.<TypeLiteral>of(null));
578       bind(new TypeLiteral<Key<String>>() {}).toProvider(Providers.<Key<String>>of(null));
579     }
580   }
581 
testCannotBindToGuiceTypes()582   public void testCannotBindToGuiceTypes() {
583     try {
584       Guice.createInjector(new OuterCoreModule());
585       fail();
586     } catch (CreationException expected) {
587       assertContains(
588           expected.getMessage(),
589           "Binding to core guice framework type is not allowed: AbstractModule.",
590           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
591           asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
592           "Binding to core guice framework type is not allowed: Binder.",
593           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
594           asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
595           "Binding to core guice framework type is not allowed: Binding.",
596           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
597           asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
598           "Binding to core guice framework type is not allowed: Injector.",
599           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
600           asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
601           "Binding to core guice framework type is not allowed: Key.",
602           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
603           asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
604           "Binding to core guice framework type is not allowed: Module.",
605           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
606           asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
607           "Binding to Provider is not allowed.",
608           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
609           asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
610           "Binding to core guice framework type is not allowed: Scope.",
611           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
612           asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
613           "Binding to core guice framework type is not allowed: Stage.",
614           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
615           asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
616           "Binding to core guice framework type is not allowed: TypeLiteral.",
617           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
618           asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
619           "Binding to core guice framework type is not allowed: Key.",
620           "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
621           asModuleChain(OuterCoreModule.class, InnerCoreModule.class));
622     }
623   }
624 
625   static class MissingParameter {
626     @Inject
MissingParameter(NoInjectConstructor noInjectConstructor)627     MissingParameter(NoInjectConstructor noInjectConstructor) {}
628   }
629 
630   static class NoInjectConstructor {
NoInjectConstructor()631     private NoInjectConstructor() {}
632   }
633 
634   @ProvidedBy(HasProvidedBy1Provider.class)
635   interface HasProvidedBy1 {}
636 
637   static class HasProvidedBy1Provider implements Provider<HasProvidedBy1> {
638     @Override
get()639     public HasProvidedBy1 get() {
640       return new HasProvidedBy1() {};
641     }
642   }
643 
644   @ImplementedBy(ImplementsHasImplementedBy1.class)
645   interface HasImplementedBy1 {}
646 
647   static class ImplementsHasImplementedBy1 implements HasImplementedBy1 {}
648 
649   @ProvidedBy(HasProvidedBy2Provider.class)
650   static class HasProvidedBy2 {}
651 
652   static class HasProvidedBy2Provider implements Provider<HasProvidedBy2> {
653     @Override
get()654     public HasProvidedBy2 get() {
655       return new HasProvidedBy2() {};
656     }
657   }
658 
659   @ImplementedBy(ExtendsHasImplementedBy2.class)
660   static class HasImplementedBy2 {}
661 
662   static class ExtendsHasImplementedBy2 extends HasImplementedBy2 {}
663 
664   static class JustAClass {}
665 
666   @ImplementedBy(ImplementsHasImplementedByThatNeedsAnotherImplementedBy.class)
667   static interface HasImplementedByThatNeedsAnotherImplementedBy {}
668 
669   static class ImplementsHasImplementedByThatNeedsAnotherImplementedBy
670       implements HasImplementedByThatNeedsAnotherImplementedBy {
671     @Inject
ImplementsHasImplementedByThatNeedsAnotherImplementedBy(HasImplementedBy1 h1n1)672     ImplementsHasImplementedByThatNeedsAnotherImplementedBy(HasImplementedBy1 h1n1) {}
673   }
674 
675   @ImplementedBy(ImplementsHasImplementedByThatWantsExplicit.class)
676   static interface HasImplementedByThatWantsExplicit {}
677 
678   static class ImplementsHasImplementedByThatWantsExplicit
679       implements HasImplementedByThatWantsExplicit {
680     @Inject
ImplementsHasImplementedByThatWantsExplicit(JustAnInterface jai)681     ImplementsHasImplementedByThatWantsExplicit(JustAnInterface jai) {}
682   }
683 
684   static interface JustAnInterface {}
685 
686   //  public void testBindInterfaceWithoutImplementation() {
687   //    Guice.createInjector(new AbstractModule() {
688   //      protected void configure() {
689   //        bind(Runnable.class);
690   //      }
691   //    }).getInstance(Runnable.class);
692   //  }
693 
694   enum Roshambo {
695     ROCK,
696     SCISSORS,
697     PAPER
698   }
699 
testInjectRawProvider()700   public void testInjectRawProvider() {
701     try {
702       Guice.createInjector().getInstance(Provider.class);
703       fail();
704     } catch (ConfigurationException expected) {
705       Asserts.assertContains(
706           expected.getMessage(),
707           "1) Cannot inject a Provider that has no type parameter",
708           "while locating " + Provider.class.getName());
709     }
710   }
711 }
712