1 /** 2 * Copyright (C) 2006 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.name.Names.named; 20 21 import com.google.inject.name.Named; 22 23 import junit.framework.TestCase; 24 25 import java.util.Arrays; 26 import java.util.List; 27 28 /** 29 * @author crazybob@google.com (Bob Lee) 30 */ 31 public class ProviderInjectionTest extends TestCase { 32 testProviderInjection()33 public void testProviderInjection() throws CreationException { 34 Injector injector = Guice.createInjector(new AbstractModule() { 35 protected void configure() { 36 bind(Bar.class); 37 bind(SampleSingleton.class).in(Scopes.SINGLETON); 38 } 39 }); 40 41 Foo foo = injector.getInstance(Foo.class); 42 43 Bar bar = foo.barProvider.get(); 44 assertNotNull(bar); 45 assertNotSame(bar, foo.barProvider.get()); 46 47 SampleSingleton singleton = foo.singletonProvider.get(); 48 assertNotNull(singleton); 49 assertSame(singleton, foo.singletonProvider.get()); 50 } 51 52 /** Test for bug 155. */ testProvidersAreInjectedWhenBound()53 public void testProvidersAreInjectedWhenBound() { 54 Module m = new AbstractModule() { 55 @Override 56 protected void configure() { 57 bind(Bar.class).toProvider(new Provider<Bar>() { 58 @SuppressWarnings("unused") 59 @Inject void cantBeCalled(Baz baz) { 60 fail("Can't have called this method since Baz is not bound."); 61 } 62 public Bar get() { 63 return new Bar() {}; 64 } 65 }); 66 } 67 }; 68 69 try { 70 Guice.createInjector(m); 71 fail("Should have thrown a CreationException"); 72 } 73 catch (CreationException expected) { 74 } 75 } 76 77 /** 78 * When custom providers are used at injector creation time, they should be 79 * injected before use. In this testcase, we verify that a provider for 80 * List.class is injected before it is used. 81 */ testProvidersAreInjectedBeforeTheyAreUsed()82 public void testProvidersAreInjectedBeforeTheyAreUsed() { 83 Injector injector = Guice.createInjector(new AbstractModule() { 84 public void configure() { 85 // should bind String to "[true]" 86 bind(String.class).toProvider(new Provider<String>() { 87 private String value; 88 @Inject void initialize(List list) { 89 value = list.toString(); 90 } 91 public String get() { 92 return value; 93 } 94 }); 95 96 // should bind List to [true] 97 bind(List.class).toProvider(new Provider<List>() { 98 @Inject Boolean injectedYet = Boolean.FALSE; 99 public List get() { 100 return Arrays.asList(injectedYet); 101 } 102 }); 103 104 // should bind Boolean to true 105 bind(Boolean.class).toInstance(Boolean.TRUE); 106 } 107 }); 108 109 assertEquals("Providers not injected before use", 110 "[true]", 111 injector.getInstance(String.class)); 112 } 113 114 /** 115 * This test ensures that regardless of binding order, instances are injected 116 * before they are used. It injects mutable Count objects and records their 117 * value at the time that they're injected. 118 */ testCreationTimeInjectionOrdering()119 public void testCreationTimeInjectionOrdering() { 120 Injector injector = Guice.createInjector(new AbstractModule() { 121 protected void configure() { 122 // instance injection 123 bind(Count.class).annotatedWith(named("a")).toInstance(new Count(0) { 124 @Inject void initialize(@Named("b") Count bCount) { 125 value = bCount.value + 1; 126 } 127 }); 128 129 // provider injection 130 bind(Count.class).annotatedWith(named("b")).toProvider(new Provider<Count>() { 131 Count count; 132 @Inject void initialize(@Named("c") Count cCount) { 133 count = new Count(cCount.value + 2); 134 } 135 public Count get() { 136 return count; 137 } 138 }); 139 140 // field and method injection, fields first 141 bind(Count.class).annotatedWith(named("c")).toInstance(new Count(0) { 142 @Inject @Named("d") Count dCount; 143 @Inject void initialize(@Named("e") Count eCount) { 144 value = dCount.value + eCount.value + 4; 145 } 146 }); 147 148 // static injection 149 requestStaticInjection(StaticallyInjectable.class); 150 151 bind(Count.class).annotatedWith(named("d")).toInstance(new Count(8)); 152 bind(Count.class).annotatedWith(named("e")).toInstance(new Count(16)); 153 } 154 }); 155 156 assertEquals(28, injector.getInstance(Key.get(Count.class, named("c"))).value); 157 assertEquals(30, injector.getInstance(Key.get(Count.class, named("b"))).value); 158 assertEquals(31, injector.getInstance(Key.get(Count.class, named("a"))).value); 159 assertEquals(28, StaticallyInjectable.cCountAtInjectionTime); 160 } 161 162 static class Count { 163 int value; Count(int value)164 Count(int value) { 165 this.value = value; 166 } 167 } 168 169 static class StaticallyInjectable { 170 static int cCountAtInjectionTime; initialize(@amed"c") Count cCount)171 @Inject static void initialize(@Named("c") Count cCount) { 172 cCountAtInjectionTime = cCount.value; 173 } 174 } 175 176 static class Foo { 177 @Inject Provider<Bar> barProvider; 178 @Inject Provider<SampleSingleton> singletonProvider; 179 } 180 181 static class Bar {} 182 183 static class SampleSingleton {} 184 185 interface Baz { } 186 187 } 188