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