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