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