1 /* 2 * Copyright (C) 2014 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.testing.fieldbinder; 18 19 import static com.google.inject.Asserts.assertContains; 20 import static java.lang.annotation.RetentionPolicy.RUNTIME; 21 22 import com.google.inject.BindingAnnotation; 23 import com.google.inject.ConfigurationException; 24 import com.google.inject.CreationException; 25 import com.google.inject.Guice; 26 import com.google.inject.Inject; 27 import com.google.inject.Injector; 28 import com.google.inject.Key; 29 import com.google.inject.Provider; 30 import com.google.inject.ProvisionException; 31 import com.google.inject.name.Named; 32 import com.google.inject.name.Names; 33 import com.google.inject.util.Providers; 34 35 import junit.framework.TestCase; 36 37 import java.lang.annotation.Retention; 38 import java.util.Arrays; 39 import java.util.List; 40 41 import javax.inject.Qualifier; 42 43 /** Unit tests for {@link BoundFieldModule}. */ 44 public class BoundFieldModuleTest extends TestCase { testBindingNothing()45 public void testBindingNothing() { 46 Object instance = new Object() {}; 47 48 BoundFieldModule module = BoundFieldModule.of(instance); 49 Guice.createInjector(module); 50 51 // If we didn't throw an exception, we succeeded. 52 } 53 testBindingOnePrivate()54 public void testBindingOnePrivate() { 55 final Integer testValue = 1024; 56 Object instance = new Object() { 57 @Bind private Integer anInt = testValue; 58 }; 59 60 BoundFieldModule module = BoundFieldModule.of(instance); 61 Injector injector = Guice.createInjector(module); 62 63 assertEquals(testValue, injector.getInstance(Integer.class)); 64 } 65 testBindingOnePublic()66 public void testBindingOnePublic() { 67 final Integer testValue = 1024; 68 Object instance = new Object() { 69 @Bind public Integer anInt = testValue; 70 }; 71 72 BoundFieldModule module = BoundFieldModule.of(instance); 73 Injector injector = Guice.createInjector(module); 74 75 assertEquals(testValue, injector.getInstance(Integer.class)); 76 } 77 78 private static class FieldBindableClass { 79 @Bind Integer anInt; 80 FieldBindableClass(Integer anInt)81 FieldBindableClass(Integer anInt) { 82 this.anInt = anInt; 83 } 84 } 85 86 private static class FieldBindableSubclass extends FieldBindableClass { FieldBindableSubclass(Integer anInt)87 FieldBindableSubclass(Integer anInt) { 88 super(anInt); 89 } 90 } 91 testSuperTypeBinding()92 public void testSuperTypeBinding() { 93 FieldBindableSubclass instance = new FieldBindableSubclass(1024); 94 95 BoundFieldModule module = BoundFieldModule.of(instance); 96 Injector injector = Guice.createInjector(module); 97 98 assertEquals(instance.anInt, injector.getInstance(Integer.class)); 99 } 100 testBindingTwo()101 public void testBindingTwo() { 102 final Integer testValue = 1024; 103 final String testString = "Hello World!"; 104 Object instance = new Object() { 105 @Bind private Integer anInt = testValue; 106 @Bind private String aString = testString; 107 }; 108 109 BoundFieldModule module = BoundFieldModule.of(instance); 110 Injector injector = Guice.createInjector(module); 111 112 assertEquals(testValue, injector.getInstance(Integer.class)); 113 assertEquals(testString, injector.getInstance(String.class)); 114 } 115 testBindingSuperType()116 public void testBindingSuperType() { 117 final Integer testValue = 1024; 118 Object instance = new Object() { 119 @Bind(to = Number.class) private Integer anInt = testValue; 120 }; 121 122 BoundFieldModule module = BoundFieldModule.of(instance); 123 Injector injector = Guice.createInjector(module); 124 125 assertEquals(testValue, injector.getInstance(Number.class)); 126 } 127 testBindingSuperTypeAccessSubType()128 public void testBindingSuperTypeAccessSubType() { 129 final Integer testValue = 1024; 130 Object instance = new Object() { 131 @Bind(to = Number.class) private Integer anInt = testValue; 132 }; 133 134 BoundFieldModule module = BoundFieldModule.of(instance); 135 Injector injector = Guice.createInjector(module); 136 137 try { 138 injector.getInstance(Integer.class); 139 } catch (ConfigurationException e) { 140 assertContains( 141 e.getMessage(), 142 "Could not find a suitable constructor in java.lang.Integer"); 143 } 144 } 145 testBindingIncorrectTypeProviderFails()146 public void testBindingIncorrectTypeProviderFails() { 147 final Integer testValue = 1024; 148 Object instance = new Object() { 149 @Bind(to = String.class) private Provider<Integer> anIntProvider = new Provider<Integer>() { 150 @Override public Integer get() { 151 return testValue; 152 } 153 }; 154 }; 155 156 BoundFieldModule module = BoundFieldModule.of(instance); 157 158 try { 159 Guice.createInjector(module); 160 fail(); 161 } catch (CreationException e) { 162 assertContains( 163 e.getMessage(), 164 "Requested binding type \"java.lang.String\" is not " 165 + "assignable from field binding type \"java.lang.Integer\""); 166 } 167 } 168 169 @BindingAnnotation 170 @Retention(RUNTIME) 171 private static @interface SomeBindingAnnotation {} 172 testBindingWithBindingAnnotation()173 public void testBindingWithBindingAnnotation() { 174 final Integer testValue1 = 1024, testValue2 = 2048; 175 Object instance = new Object() { 176 @Bind private Integer anInt = testValue1; 177 178 @Bind 179 @SomeBindingAnnotation 180 private Integer anotherInt = testValue2; 181 }; 182 183 BoundFieldModule module = BoundFieldModule.of(instance); 184 Injector injector = Guice.createInjector(module); 185 186 assertEquals(testValue1, injector.getInstance(Integer.class)); 187 assertEquals( 188 testValue2, 189 injector.getInstance(Key.get(Integer.class, SomeBindingAnnotation.class))); 190 } 191 192 @Qualifier 193 @Retention(RUNTIME) 194 private static @interface SomeQualifier {} 195 testBindingWithQualifier()196 public void testBindingWithQualifier() { 197 final Integer testValue1 = 1024, testValue2 = 2048; 198 Object instance = new Object() { 199 @Bind private Integer anInt = testValue1; 200 201 @Bind 202 @SomeQualifier 203 private Integer anotherInt = testValue2; 204 }; 205 206 BoundFieldModule module = BoundFieldModule.of(instance); 207 Injector injector = Guice.createInjector(module); 208 209 assertEquals(testValue1, injector.getInstance(Integer.class)); 210 assertEquals( 211 testValue2, 212 injector.getInstance(Key.get(Integer.class, SomeQualifier.class))); 213 } 214 testCanReuseBindingAnnotationsWithDifferentValues()215 public void testCanReuseBindingAnnotationsWithDifferentValues() { 216 final Integer testValue1 = 1024, testValue2 = 2048; 217 final String name1 = "foo", name2 = "bar"; 218 Object instance = new Object() { 219 @Bind 220 @Named(name1) 221 private Integer anInt = testValue1; 222 223 @Bind 224 @Named(name2) 225 private Integer anotherInt = testValue2; 226 }; 227 228 BoundFieldModule module = BoundFieldModule.of(instance); 229 Injector injector = Guice.createInjector(module); 230 231 assertEquals( 232 testValue1, 233 injector.getInstance(Key.get(Integer.class, Names.named(name1)))); 234 assertEquals( 235 testValue2, 236 injector.getInstance(Key.get(Integer.class, Names.named(name2)))); 237 } 238 testBindingWithValuedBindingAnnotation()239 public void testBindingWithValuedBindingAnnotation() { 240 final Integer testValue1 = 1024, testValue2 = 2048; 241 final String name = "foo"; 242 Object instance = new Object() { 243 @Bind private Integer anInt = testValue1; 244 245 @Bind 246 @Named(name) 247 private Integer anotherInt = testValue2; 248 }; 249 250 BoundFieldModule module = BoundFieldModule.of(instance); 251 Injector injector = Guice.createInjector(module); 252 253 assertEquals(testValue1, injector.getInstance(Integer.class)); 254 assertEquals( 255 testValue2, 256 injector.getInstance(Key.get(Integer.class, Names.named(name)))); 257 } 258 testBindingWithGenerics()259 public void testBindingWithGenerics() { 260 final List<Integer> testIntList = Arrays.asList(new Integer[] {1, 2, 3}); 261 final List<Boolean> testBoolList = Arrays.asList(new Boolean[] {true, true, false}); 262 Object instance = new Object() { 263 @Bind private List<Integer> anIntList = testIntList; 264 @Bind private List<Boolean> aBoolList = testBoolList; 265 }; 266 267 BoundFieldModule module = BoundFieldModule.of(instance); 268 Injector injector = Guice.createInjector(module); 269 270 assertEquals(testIntList, injector.getInstance(new Key<List<Integer>>() {})); 271 assertEquals(testBoolList, injector.getInstance(new Key<List<Boolean>>() {})); 272 } 273 testBoundValueDoesntChange()274 public void testBoundValueDoesntChange() { 275 Integer testValue = 1024; 276 FieldBindableClass instance = new FieldBindableClass(testValue); 277 278 BoundFieldModule module = BoundFieldModule.of(instance); 279 Injector injector = Guice.createInjector(module); 280 281 assertEquals(testValue, injector.getInstance(Integer.class)); 282 instance.anInt++; 283 assertEquals(testValue, injector.getInstance(Integer.class)); 284 } 285 testIncompatibleBindingType()286 public void testIncompatibleBindingType() { 287 final Integer testInt = 1024; 288 Object instance = new Object() { 289 @Bind(to = String.class) private Integer anInt = testInt; 290 }; 291 292 BoundFieldModule module = BoundFieldModule.of(instance); 293 294 try { 295 Guice.createInjector(module); 296 fail(); 297 } catch (CreationException e) { 298 assertContains(e.getMessage(), 299 "Requested binding type \"java.lang.String\" is not assignable from field binding type " 300 + "\"java.lang.Integer\""); 301 } 302 } 303 testFailureOnMultipleBindingAnnotations()304 public void testFailureOnMultipleBindingAnnotations() { 305 final Integer testInt = 1024; 306 Object instance = new Object() { 307 @Bind 308 @Named("a") 309 @SomeBindingAnnotation 310 private Integer anInt = testInt; 311 }; 312 313 BoundFieldModule module = BoundFieldModule.of(instance); 314 315 try { 316 Guice.createInjector(module); 317 } catch (CreationException e) { 318 assertContains(e.getMessage(), "More than one annotation is specified for this binding."); 319 } 320 } 321 testBindingSuperTypeAndBindingAnnotation()322 public void testBindingSuperTypeAndBindingAnnotation() { 323 final Integer testValue = 1024; 324 Object instance = new Object() { 325 @Bind(to = Number.class) 326 @Named("foo") 327 private Integer anInt = testValue; 328 }; 329 330 BoundFieldModule module = BoundFieldModule.of(instance); 331 Injector injector = Guice.createInjector(module); 332 333 assertEquals(testValue, injector.getInstance(Key.get(Number.class, Names.named("foo")))); 334 } 335 testBindingProvider()336 public void testBindingProvider() { 337 final Integer testValue = 1024; 338 Object instance = new Object() { 339 @Bind private Provider<Integer> anInt = new Provider<Integer>() { 340 @Override public Integer get() { 341 return testValue; 342 } 343 }; 344 }; 345 346 BoundFieldModule module = BoundFieldModule.of(instance); 347 Injector injector = Guice.createInjector(module); 348 349 assertEquals(testValue, injector.getInstance(Integer.class)); 350 } 351 testBindingNullField()352 public void testBindingNullField() { 353 Object instance = new Object() { 354 @Bind private Integer anInt = null; 355 }; 356 357 BoundFieldModule module = BoundFieldModule.of(instance); 358 359 try { 360 Guice.createInjector(module); 361 fail(); 362 } catch (CreationException e) { 363 assertContains(e.getMessage(), 364 "Binding to null values is not allowed. " 365 + "Use Providers.of(null) if this is your intended behavior."); 366 } 367 } 368 testBindingNullProvider()369 public void testBindingNullProvider() { 370 Object instance = new Object() { 371 @Bind private Provider<Integer> anIntProvider = null; 372 }; 373 374 BoundFieldModule module = BoundFieldModule.of(instance); 375 376 try { 377 Guice.createInjector(module); 378 fail(); 379 } catch (CreationException e) { 380 assertContains(e.getMessage(), 381 "Binding to null values is not allowed. " 382 + "Use Providers.of(null) if this is your intended behavior."); 383 } 384 } 385 386 private static class IntegerProvider implements Provider<Integer> { 387 private final Integer value; 388 IntegerProvider(Integer value)389 IntegerProvider(Integer value) { 390 this.value = value; 391 } 392 get()393 @Override public Integer get() { 394 return value; 395 } 396 } 397 testProviderSubclassesBindToTheProviderItself()398 public void testProviderSubclassesBindToTheProviderItself() { 399 final IntegerProvider integerProvider = new IntegerProvider(1024); 400 Object instance = new Object() { 401 @Bind private IntegerProvider anIntProvider = integerProvider; 402 }; 403 404 BoundFieldModule module = BoundFieldModule.of(instance); 405 Injector injector = Guice.createInjector(module); 406 407 assertEquals(integerProvider, injector.getInstance(IntegerProvider.class)); 408 } 409 testProviderSubclassesDoNotBindParameterizedType()410 public void testProviderSubclassesDoNotBindParameterizedType() { 411 final Integer testValue = 1024; 412 Object instance = new Object() { 413 @Bind private IntegerProvider anIntProvider = new IntegerProvider(testValue); 414 }; 415 416 BoundFieldModule module = BoundFieldModule.of(instance); 417 Injector injector = Guice.createInjector(module); 418 419 try { 420 injector.getInstance(Integer.class); 421 fail(); 422 } catch (ConfigurationException e) { 423 assertContains(e.getMessage(), "Could not find a suitable constructor in java.lang.Integer."); 424 } 425 } 426 427 private static class ParameterizedObject<T> { ParameterizedObject(T instance)428 ParameterizedObject(T instance) { 429 this.instance = instance; 430 } 431 432 @Bind private T instance; 433 } 434 testBindParameterizedTypeFails()435 public void testBindParameterizedTypeFails() { 436 ParameterizedObject<Integer> instance = new ParameterizedObject<Integer>(0); 437 438 BoundFieldModule module = BoundFieldModule.of(instance); 439 440 try { 441 Guice.createInjector(module); 442 fail(); 443 } catch (CreationException e) { 444 assertContains(e.getMessage(), "T cannot be used as a key; It is not fully specified."); 445 } 446 } 447 testBindSubclassOfParameterizedTypeSucceeds()448 public void testBindSubclassOfParameterizedTypeSucceeds() { 449 final Integer testValue = 1024; 450 ParameterizedObject<Integer> instance = new ParameterizedObject<Integer>(testValue) {}; 451 452 BoundFieldModule module = BoundFieldModule.of(instance); 453 Injector injector = Guice.createInjector(module); 454 455 assertEquals(testValue, injector.getInstance(Integer.class)); 456 } 457 testBindArray()458 public void testBindArray() { 459 final Integer[] testArray = new Integer[] { 1024, 2048 }; 460 Object instance = new Object() { 461 @Bind private Integer[] anIntArray = testArray; 462 }; 463 464 BoundFieldModule module = BoundFieldModule.of(instance); 465 Injector injector = Guice.createInjector(module); 466 467 assertEquals(testArray, injector.getInstance(Integer[].class)); 468 } 469 testRawProviderCannotBeBound()470 public void testRawProviderCannotBeBound() { 471 final Integer testValue = 1024; 472 Object instance = new Object() { 473 @Bind private Provider anIntProvider = new Provider() { 474 @Override public Object get() { 475 return testValue; 476 } 477 }; 478 }; 479 480 BoundFieldModule module = BoundFieldModule.of(instance); 481 482 try { 483 Guice.createInjector(module); 484 fail(); 485 } catch (CreationException e) { 486 assertContains(e.getMessage(), 487 "Non parameterized Provider fields must have an " 488 + "explicit binding class via @Bind(to = Foo.class)"); 489 } 490 } 491 testExplicitlyBoundRawProviderCanBeBound()492 public void testExplicitlyBoundRawProviderCanBeBound() { 493 final Integer testValue = 1024; 494 Object instance = new Object() { 495 @Bind(to = Integer.class) private Provider anIntProvider = new Provider() { 496 @Override public Object get() { 497 return testValue; 498 } 499 }; 500 }; 501 502 BoundFieldModule module = BoundFieldModule.of(instance); 503 Injector injector = Guice.createInjector(module); 504 505 assertEquals(testValue, injector.getInstance(Integer.class)); 506 } 507 testRawProviderCanBindToIncorrectType()508 public void testRawProviderCanBindToIncorrectType() { 509 final Integer testValue = 1024; 510 Object instance = new Object() { 511 @Bind(to = String.class) private Provider anIntProvider = new Provider() { 512 @Override public Object get() { 513 return testValue; 514 } 515 }; 516 }; 517 518 BoundFieldModule module = BoundFieldModule.of(instance); 519 Injector injector = Guice.createInjector(module); 520 521 assertEquals(testValue, injector.getInstance(String.class)); 522 } 523 testMultipleErrorsAreAggregated()524 public void testMultipleErrorsAreAggregated() { 525 Object instance = new Object() { 526 @Bind private Provider aProvider; 527 @Bind(to = String.class) private Integer anInt; 528 }; 529 530 BoundFieldModule module = BoundFieldModule.of(instance); 531 try { 532 Guice.createInjector(module); 533 } catch (CreationException e) { 534 assertEquals(2, e.getErrorMessages().size()); 535 } 536 } 537 testBindingProviderWithProviderSubclassValue()538 public void testBindingProviderWithProviderSubclassValue() { 539 final Integer testValue = 1024; 540 Object instance = new Object() { 541 @Bind private Provider<Integer> anIntProvider = new IntegerProvider(testValue); 542 }; 543 544 BoundFieldModule module = BoundFieldModule.of(instance); 545 Injector injector = Guice.createInjector(module); 546 547 assertEquals(testValue, injector.getInstance(Integer.class)); 548 } 549 testBoundFieldsCannotBeInjected()550 public void testBoundFieldsCannotBeInjected() { 551 Object instance = new Object() { 552 @Bind 553 @Inject 554 Integer anInt = 0; 555 }; 556 557 BoundFieldModule module = BoundFieldModule.of(instance); 558 559 try { 560 Guice.createInjector(module); 561 } catch (CreationException e) { 562 assertContains( 563 e.getMessage(), 564 "Fields annotated with both @Bind and @Inject are illegal."); 565 } 566 } 567 testIncrementingProvider()568 public void testIncrementingProvider() { 569 final Integer testBaseValue = 1024; 570 Object instance = new Object() { 571 @Bind private Provider<Integer> anIntProvider = new Provider<Integer>() { 572 private int value = testBaseValue; 573 574 @Override public Integer get() { 575 return value++; 576 } 577 }; 578 }; 579 580 BoundFieldModule module = BoundFieldModule.of(instance); 581 Injector injector = Guice.createInjector(module); 582 583 assertEquals(testBaseValue, injector.getInstance(Integer.class)); 584 assertEquals((Integer) (testBaseValue + 1), injector.getInstance(Integer.class)); 585 assertEquals((Integer) (testBaseValue + 2), injector.getInstance(Integer.class)); 586 } 587 testProviderDoesNotProvideDuringInjectorConstruction()588 public void testProviderDoesNotProvideDuringInjectorConstruction() { 589 Object instance = new Object() { 590 @Bind private Provider<Integer> myIntProvider = new Provider<Integer>() { 591 @Override public Integer get() { 592 throw new UnsupportedOperationException(); 593 } 594 }; 595 }; 596 597 BoundFieldModule module = BoundFieldModule.of(instance); 598 Guice.createInjector(module); 599 600 // If we don't throw an exception, we succeeded. 601 } 602 603 private static class InvalidBindableClass { 604 @Bind(to = String.class) Integer anInt; 605 } 606 testIncompatibleBindingTypeStackTraceHasUserFrame()607 public void testIncompatibleBindingTypeStackTraceHasUserFrame() { 608 Object instance = new InvalidBindableClass(); 609 610 BoundFieldModule module = BoundFieldModule.of(instance); 611 612 try { 613 Guice.createInjector(module); 614 fail(); 615 } catch (CreationException e) { 616 assertContains(e.getMessage(), "at " + InvalidBindableClass.class.getName() + " field anInt"); 617 } 618 } 619 620 private static class InjectedNumberProvider implements Provider<Number> { 621 @Inject Integer anInt; 622 get()623 @Override public Number get() { 624 return anInt; 625 } 626 } 627 testBoundProvidersAreInjected()628 public void testBoundProvidersAreInjected() { 629 final Integer testValue = 1024; 630 Object instance = new Object() { 631 @Bind private Integer anInt = testValue; 632 @Bind private Provider<Number> aNumberProvider = new InjectedNumberProvider(); 633 }; 634 635 BoundFieldModule module = BoundFieldModule.of(instance); 636 Injector injector = Guice.createInjector(module); 637 638 assertEquals(testValue, injector.getInstance(Number.class)); 639 } 640 testBoundInstancesAreInjected()641 public void testBoundInstancesAreInjected() { 642 final Integer testValue = 1024; 643 final InjectedNumberProvider testNumberProvider = new InjectedNumberProvider(); 644 Object instance = new Object() { 645 @Bind private Integer anInt = testValue; 646 @Bind private InjectedNumberProvider aNumberProvider = testNumberProvider; 647 }; 648 649 BoundFieldModule module = BoundFieldModule.of(instance); 650 Guice.createInjector(module); 651 652 assertEquals(testValue, testNumberProvider.anInt); 653 } 654 655 private static class InvalidBindableSubclass extends InvalidBindableClass {} 656 testClassIsPrintedInErrorsWhenCauseIsSuperclass()657 public void testClassIsPrintedInErrorsWhenCauseIsSuperclass() { 658 Object instance = new InvalidBindableSubclass(); 659 660 BoundFieldModule module = BoundFieldModule.of(instance); 661 662 try { 663 Guice.createInjector(module); 664 } catch (CreationException e) { 665 assertContains( 666 e.getMessage(), 667 "Requested binding type \"java.lang.String\" is not assignable from field binding type " 668 + "\"java.lang.Integer\""); 669 } 670 } 671 672 private static class FieldBindableSubclass2 extends FieldBindableClass { 673 @Bind Number aNumber; 674 FieldBindableSubclass2(Integer anInt, Number aNumber)675 FieldBindableSubclass2(Integer anInt, Number aNumber) { 676 super(anInt); 677 this.aNumber = aNumber; 678 } 679 } 680 testFieldsAreBoundFromFullClassHierarchy()681 public void testFieldsAreBoundFromFullClassHierarchy() { 682 final Integer testValue1 = 1024, testValue2 = 2048; 683 FieldBindableSubclass2 instance = new FieldBindableSubclass2(testValue1, testValue2); 684 685 BoundFieldModule module = BoundFieldModule.of(instance); 686 Injector injector = Guice.createInjector(module); 687 688 assertEquals(testValue1, injector.getInstance(Integer.class)); 689 assertEquals(testValue2, injector.getInstance(Number.class)); 690 } 691 692 static final class LazyClass { 693 @Bind(lazy = true) Integer foo = 1; 694 } 695 testFieldBound_lazy()696 public void testFieldBound_lazy() { 697 LazyClass asProvider = new LazyClass(); 698 Injector injector = Guice.createInjector(BoundFieldModule.of(asProvider)); 699 assertEquals(1, injector.getInstance(Integer.class).intValue()); 700 asProvider.foo++; 701 assertEquals(2, injector.getInstance(Integer.class).intValue()); 702 } 703 testFieldBound_lazy_rejectNull()704 public void testFieldBound_lazy_rejectNull() { 705 LazyClass asProvider = new LazyClass(); 706 Injector injector = Guice.createInjector(BoundFieldModule.of(asProvider)); 707 assertEquals(1, injector.getInstance(Integer.class).intValue()); 708 asProvider.foo = null; 709 try { 710 injector.getInstance(Integer.class); 711 fail(); 712 } catch (ProvisionException e) { 713 assertContains(e.getMessage(), 714 "Binding to null values is not allowed. " 715 + "Use Providers.of(null) if this is your intended behavior."); 716 } 717 } 718 719 static final class LazyProviderClass { 720 @Bind(lazy = true) Provider<Integer> foo = Providers.of(null); 721 } 722 testFieldBoundAsProvider_rejectProvider()723 public void testFieldBoundAsProvider_rejectProvider() { 724 LazyProviderClass asProvider = new LazyProviderClass(); 725 try { 726 Guice.createInjector(BoundFieldModule.of(asProvider)); 727 fail(); 728 } catch (CreationException e) { 729 assertContains(e.getMessage(), "'lazy' is incompatible with Provider valued fields"); 730 } 731 } 732 } 733