• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Asserts.assertContains;
20 import static com.google.inject.Asserts.getDeclaringSourcePart;
21 import static java.lang.annotation.RetentionPolicy.RUNTIME;
22 
23 import com.google.inject.matcher.Matchers;
24 import com.google.inject.spi.TypeEncounter;
25 import com.google.inject.spi.TypeListener;
26 import java.lang.annotation.Retention;
27 import junit.framework.TestCase;
28 
29 /** @author crazybob@google.com (Bob Lee) */
30 public class RequestInjectionTest extends TestCase {
31 
32   @Retention(RUNTIME)
33   @BindingAnnotation
34   @interface ForField {}
35 
36   @Retention(RUNTIME)
37   @BindingAnnotation
38   @interface ForMethod {}
39 
40   @Override
setUp()41   protected void setUp() throws Exception {
42     super.setUp();
43     HasInjections.staticField = 0;
44     HasInjections.staticMethod = null;
45   }
46 
testInjectMembers()47   public void testInjectMembers() {
48     final HasInjections hi = new HasInjections();
49 
50     Guice.createInjector(
51         new AbstractModule() {
52           @Override
53           protected void configure() {
54             bindConstant().annotatedWith(ForMethod.class).to("test");
55             bindConstant().annotatedWith(ForField.class).to(5);
56             requestInjection(hi);
57           }
58         });
59 
60     assertEquals("test", hi.instanceMethod);
61     assertEquals(5, hi.instanceField);
62     assertNull(HasInjections.staticMethod);
63     assertEquals(0, HasInjections.staticField);
64   }
65 
testInjectStatics()66   public void testInjectStatics() throws CreationException {
67     Guice.createInjector(
68         new AbstractModule() {
69           @Override
70           protected void configure() {
71             bindConstant().annotatedWith(ForMethod.class).to("test");
72             bindConstant().annotatedWith(ForField.class).to(5);
73             requestStaticInjection(HasInjections.class);
74           }
75         });
76 
77     assertEquals("test", HasInjections.staticMethod);
78     assertEquals(5, HasInjections.staticField);
79   }
80 
testInjectMembersAndStatics()81   public void testInjectMembersAndStatics() {
82     final HasInjections hi = new HasInjections();
83 
84     Guice.createInjector(
85         new AbstractModule() {
86           @Override
87           protected void configure() {
88             bindConstant().annotatedWith(ForMethod.class).to("test");
89             bindConstant().annotatedWith(ForField.class).to(5);
90             requestStaticInjection(HasInjections.class);
91             requestInjection(hi);
92           }
93         });
94 
95     assertEquals("test", hi.instanceMethod);
96     assertEquals(5, hi.instanceField);
97     assertEquals("test", HasInjections.staticMethod);
98     assertEquals(5, HasInjections.staticField);
99   }
100 
testValidationErrorOnInjectedMembers()101   public void testValidationErrorOnInjectedMembers() {
102     try {
103       Guice.createInjector(
104           new AbstractModule() {
105             @Override
106             protected void configure() {
107               requestInjection(new NeedsRunnable());
108             }
109           });
110       fail("Expected CreationException");
111     } catch (CreationException expected) {
112       assertContains(
113           expected.getMessage(),
114           "1) No implementation for java.lang.Runnable was bound",
115           "at " + NeedsRunnable.class.getName(),
116           ".runnable(RequestInjectionTest.java:");
117     }
118   }
119 
testInjectionErrorOnInjectedMembers()120   public void testInjectionErrorOnInjectedMembers() {
121     try {
122       Guice.createInjector(
123           new AbstractModule() {
124             @Override
125             protected void configure() {
126               bind(Runnable.class)
127                   .toProvider(
128                       new Provider<Runnable>() {
129                         @Override
130                         public Runnable get() {
131                           throw new UnsupportedOperationException();
132                         }
133                       });
134               requestInjection(new NeedsRunnable());
135             }
136           });
137     } catch (CreationException expected) {
138       assertContains(
139           expected.getMessage(),
140           "1) Error in custom provider, java.lang.UnsupportedOperationException",
141           "for field at " + NeedsRunnable.class.getName() + ".runnable(RequestInjectionTest.java:",
142           "at " + getClass().getName(),
143           getDeclaringSourcePart(getClass()));
144     }
145   }
146 
testUserExceptionWhileInjectingInstance()147   public void testUserExceptionWhileInjectingInstance() {
148     try {
149       Guice.createInjector(
150           new AbstractModule() {
151             @Override
152             protected void configure() {
153               requestInjection(new BlowsUpOnInject());
154             }
155           });
156       fail();
157     } catch (CreationException expected) {
158       assertContains(
159           expected.getMessage(),
160           "1) Error injecting method, java.lang.UnsupportedOperationException: Pop",
161           "at " + BlowsUpOnInject.class.getName() + ".injectInstance(RequestInjectionTest.java:");
162     }
163   }
164 
testUserExceptionWhileInjectingStatically()165   public void testUserExceptionWhileInjectingStatically() {
166     try {
167       Guice.createInjector(
168           new AbstractModule() {
169             @Override
170             protected void configure() {
171               requestStaticInjection(BlowsUpOnInject.class);
172             }
173           });
174       fail();
175     } catch (CreationException expected) {
176       assertContains(
177           expected.getMessage(),
178           "1) Error injecting method, java.lang.UnsupportedOperationException: Snap",
179           "at " + BlowsUpOnInject.class.getName() + ".injectStatically(RequestInjectionTest.java:");
180     }
181   }
182 
183   static class NeedsRunnable {
184     @Inject Runnable runnable;
185   }
186 
187   static class HasInjections {
188 
189     @Inject @ForField static int staticField;
190     @Inject @ForField int instanceField;
191 
192     static String staticMethod;
193     String instanceMethod;
194 
195     @Inject
setStaticMethod(@orMethod String staticMethod)196     static void setStaticMethod(@ForMethod String staticMethod) {
197       HasInjections.staticMethod = staticMethod;
198     }
199 
200     @Inject
setInstanceS(@orMethod String instanceS)201     void setInstanceS(@ForMethod String instanceS) {
202       this.instanceMethod = instanceS;
203     }
204   }
205 
206   static class BlowsUpOnInject {
207     @Inject
injectInstance()208     void injectInstance() {
209       throw new UnsupportedOperationException("Pop");
210     }
211 
212     @Inject
injectStatically()213     static void injectStatically() {
214       throw new UnsupportedOperationException("Snap");
215     }
216   }
217 
218   /*
219    * Tests that initializables of the same instance don't clobber
220    * membersInjectors in InitializableReference, so that they ultimately
221    * can be requested in any order.
222    */
testEarlyInjectableReferencesWithSameIdentity()223   public void testEarlyInjectableReferencesWithSameIdentity() {
224     Injector injector =
225         Guice.createInjector(
226             new AbstractModule() {
227               @Override
228               protected void configure() {
229                 // Add a listener to trigger all toInstance bindings to get an Initializable.
230                 bindListener(
231                     Matchers.any(),
232                     new TypeListener() {
233                       @Override
234                       public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {}
235                     });
236 
237                 // Bind two different Keys to the IDENTITICAL object
238                 // ORDER MATTERS! We want the String binding to push out the Object one
239                 String fail = new String("better not fail!");
240                 bind(Object.class).toInstance(fail);
241                 bind(String.class).toInstance(fail);
242 
243                 // Then try to inject those objects in a requestInjection,
244                 // letting us get into InjectableReference.get before it has
245                 // finished running through all its injections.
246                 // Each of these technically has its own InjectableReference internally.
247                 // ORDER MATTERS!.. because Object is injected first, that InjectableReference
248                 // attempts to process its members injector, but it wasn't initialized,
249                 // because String pushed it out of the queue!
250                 requestInjection(
251                     new Object() {
252                       @SuppressWarnings("unused")
253                       @Inject
254                       Object obj;
255 
256                       @SuppressWarnings("unused")
257                       @Inject
258                       String str;
259                     });
260               }
261             });
262   }
263 }
264