• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.name;
18 
19 import static com.google.inject.Asserts.assertContains;
20 
21 import com.google.inject.AbstractModule;
22 import com.google.inject.ConfigurationException;
23 import com.google.inject.CreationException;
24 import com.google.inject.Guice;
25 import com.google.inject.Inject;
26 import com.google.inject.Injector;
27 import com.google.inject.Key;
28 import com.google.inject.Module;
29 import com.google.inject.Provides;
30 import com.google.inject.internal.Annotations;
31 import java.io.Serializable;
32 import java.lang.annotation.Annotation;
33 import java.util.Properties;
34 import junit.framework.TestCase;
35 
36 /**
37  * Tests that {@code javax.inject.Named} and {@code com.google.inject.name.Named} are completely
38  * interchangeable: bindings for one can be used to inject the other.
39  *
40  * @author cgdecker@gmail.com (Colin Decker)
41  */
42 public class NamedEquivalanceTest extends TestCase {
43 
44   private static final Module GUICE_BINDING_MODULE = moduleWithAnnotation(Names.named("foo"));
45   private static final Module JSR330_BINDING_MODULE = moduleWithAnnotation(new JsrNamed("foo"));
46   private static final Module GUICE_PROVIDER_METHOD_MODULE = getGuiceBindingProviderMethodModule();
47   private static final Module JSR330_PROVIDER_METHOD_MODULE =
48       getJsr330BindingProviderMethodModule();
49 
testKeysCreatedWithDifferentTypesAreEqual()50   public void testKeysCreatedWithDifferentTypesAreEqual() {
51     assertEquals(keyForAnnotation(new GuiceNamed("foo")), keyForAnnotation(new JsrNamed("foo")));
52     assertEquals(keyForAnnotation(Names.named("foo")), keyForAnnotation(new GuiceNamed("foo")));
53     assertEquals(keyForAnnotation(Names.named("foo")), keyForAnnotation(new JsrNamed("foo")));
54 
55     assertEquals(
56         keyForAnnotationType(com.google.inject.name.Named.class),
57         keyForAnnotationType(javax.inject.Named.class));
58   }
59 
keyForAnnotation(Annotation annotation)60   private static Key<String> keyForAnnotation(Annotation annotation) {
61     return Key.get(String.class, annotation);
62   }
63 
keyForAnnotationType(Class<? extends Annotation> annotationType)64   private static Key<String> keyForAnnotationType(Class<? extends Annotation> annotationType) {
65     return Key.get(String.class, annotationType);
66   }
67 
testBindingWithNamesCanInjectBothTypes()68   public void testBindingWithNamesCanInjectBothTypes() {
69     assertInjectionsSucceed(GUICE_BINDING_MODULE);
70   }
71 
testBindingWithJsr330AnnotationCanInjectBothTypes()72   public void testBindingWithJsr330AnnotationCanInjectBothTypes() {
73     assertInjectionsSucceed(JSR330_BINDING_MODULE);
74   }
75 
testBindingWithGuiceNamedAnnotatedProviderMethodCanInjectBothTypes()76   public void testBindingWithGuiceNamedAnnotatedProviderMethodCanInjectBothTypes() {
77     assertInjectionsSucceed(GUICE_PROVIDER_METHOD_MODULE);
78   }
79 
testBindingWithJsr330NamedAnnotatedProviderMethodCanInjectBothTypes()80   public void testBindingWithJsr330NamedAnnotatedProviderMethodCanInjectBothTypes() {
81     assertInjectionsSucceed(JSR330_PROVIDER_METHOD_MODULE);
82   }
83 
testBindingDifferentTypesWithSameValueIsIgnored()84   public void testBindingDifferentTypesWithSameValueIsIgnored() {
85     assertDuplicateBinding(GUICE_BINDING_MODULE, JSR330_BINDING_MODULE, false);
86     assertDuplicateBinding(JSR330_BINDING_MODULE, GUICE_BINDING_MODULE, false);
87   }
88 
testBindingDifferentTypesWithSameValueIsAnErrorWithProviderMethods()89   public void testBindingDifferentTypesWithSameValueIsAnErrorWithProviderMethods() {
90     assertDuplicateBinding(GUICE_PROVIDER_METHOD_MODULE, JSR330_PROVIDER_METHOD_MODULE, true);
91     assertDuplicateBinding(JSR330_PROVIDER_METHOD_MODULE, GUICE_PROVIDER_METHOD_MODULE, true);
92   }
93 
testBindingDifferentTypesWithSameValueIsAnErrorMixed()94   public void testBindingDifferentTypesWithSameValueIsAnErrorMixed() {
95     assertDuplicateBinding(GUICE_BINDING_MODULE, JSR330_PROVIDER_METHOD_MODULE, true);
96     assertDuplicateBinding(JSR330_BINDING_MODULE, GUICE_PROVIDER_METHOD_MODULE, true);
97   }
98 
testMissingBindingForGuiceNamedUsesSameTypeInErrorMessage()99   public void testMissingBindingForGuiceNamedUsesSameTypeInErrorMessage() {
100     assertMissingBindingErrorMessageUsesType(GuiceNamedClient.class);
101   }
102 
testMissingBindingForJsr330NamedUsesSameTypeInErrorMessage()103   public void testMissingBindingForJsr330NamedUsesSameTypeInErrorMessage() {
104     assertMissingBindingErrorMessageUsesType(Jsr330NamedClient.class);
105   }
106 
testBindPropertiesWorksWithJsr330()107   public void testBindPropertiesWorksWithJsr330() {
108     assertInjectionsSucceed(
109         new AbstractModule() {
110           @Override
111           protected void configure() {
112             Properties properties = new Properties();
113             properties.put("foo", "bar");
114             Names.bindProperties(binder(), properties);
115           }
116         });
117   }
118 
assertMissingBindingErrorMessageUsesType(Class<?> clientType)119   private static void assertMissingBindingErrorMessageUsesType(Class<?> clientType) {
120     try {
121       Guice.createInjector().getInstance(clientType);
122       fail("should have thrown ConfigurationException");
123     } catch (ConfigurationException e) {
124       assertContains(
125           e.getMessage(),
126           "No implementation for java.lang.String annotated with "
127               + "@com.google.inject.name.Named(value="
128               + Annotations.memberValueString("foo")
129               + ") was bound.");
130     }
131   }
132 
assertDuplicateBinding(Module a, Module b, boolean fails)133   private static void assertDuplicateBinding(Module a, Module b, boolean fails) {
134     try {
135       Guice.createInjector(a, b);
136       if (fails) {
137         fail("should have thrown CreationException");
138       }
139     } catch (CreationException e) {
140       if (fails) {
141         assertContains(
142             e.getMessage(),
143             "A binding to java.lang.String annotated with @com.google.inject.name.Named(value="
144                 + Annotations.memberValueString("foo")
145                 + ") was already configured");
146       } else {
147         throw e;
148       }
149     }
150   }
151 
moduleWithAnnotation(final Annotation annotation)152   private static Module moduleWithAnnotation(final Annotation annotation) {
153     return new AbstractModule() {
154       @Override
155       protected void configure() {
156         bindConstant().annotatedWith(annotation).to("bar");
157       }
158     };
159   }
160 
161   private static void assertInjectionsSucceed(Module module) {
162     Injector injector = Guice.createInjector(module);
163     assertInjected(
164         injector.getInstance(GuiceNamedClient.class),
165         injector.getInstance(Jsr330NamedClient.class));
166   }
167 
168   private static void assertInjected(GuiceNamedClient guiceClient, Jsr330NamedClient jsr330Client) {
169     assertEquals("bar", guiceClient.foo);
170     assertEquals("bar", jsr330Client.foo);
171   }
172 
173   private static Module getJsr330BindingProviderMethodModule() {
174     return new AbstractModule() {
175 
176       @SuppressWarnings("unused")
177       @Provides
178       @javax.inject.Named("foo")
179       String provideFoo() {
180         return "bar";
181       }
182     };
183   }
184 
185   private static Module getGuiceBindingProviderMethodModule() {
186     return new AbstractModule() {
187 
188       @SuppressWarnings("unused")
189       @Provides
190       @Named("foo")
191       String provideFoo() {
192         return "bar";
193       }
194     };
195   }
196 
197   private static class GuiceNamedClient {
198     @Inject
199     @Named("foo")
200     String foo;
201   }
202 
203   private static class Jsr330NamedClient {
204     @Inject
205     @javax.inject.Named("foo")
206     String foo;
207   }
208 
209   private static class JsrNamed implements javax.inject.Named, Serializable {
210     private final String value;
211 
212     public JsrNamed(String value) {
213       this.value = value;
214     }
215 
216     @Override
217     public String value() {
218       return this.value;
219     }
220 
221     @Override
222     public int hashCode() {
223       // This is specified in java.lang.Annotation.
224       return (127 * "value".hashCode()) ^ value.hashCode();
225     }
226 
227     @Override
228     public boolean equals(Object o) {
229       if (!(o instanceof javax.inject.Named)) {
230         return false;
231       }
232 
233       javax.inject.Named other = (javax.inject.Named) o;
234       return value.equals(other.value());
235     }
236 
237     @Override
238     public String toString() {
239       return "@"
240           + javax.inject.Named.class.getName()
241           + "(value="
242           + Annotations.memberValueString(value)
243           + ")";
244     }
245 
246     @Override
247     public Class<? extends Annotation> annotationType() {
248       return javax.inject.Named.class;
249     }
250 
251     private static final long serialVersionUID = 0;
252   }
253 
254   private static class GuiceNamed implements com.google.inject.name.Named, Serializable {
255     private final String value;
256 
257     public GuiceNamed(String value) {
258       this.value = value;
259     }
260 
261     @Override
262     public String value() {
263       return this.value;
264     }
265 
266     @Override
267     public int hashCode() {
268       // This is specified in java.lang.Annotation.
269       return (127 * "value".hashCode()) ^ value.hashCode();
270     }
271 
272     @Override
273     public boolean equals(Object o) {
274       if (!(o instanceof com.google.inject.name.Named)) {
275         return false;
276       }
277 
278       com.google.inject.name.Named other = (com.google.inject.name.Named) o;
279       return value.equals(other.value());
280     }
281 
282     @Override
283     public String toString() {
284       return "@"
285           + com.google.inject.name.Named.class.getName()
286           + "(value="
287           + Annotations.memberValueString(value)
288           + ")";
289     }
290 
291     @Override
292     public Class<? extends Annotation> annotationType() {
293       return com.google.inject.name.Named.class;
294     }
295 
296     private static final long serialVersionUID = 0;
297   }
298 }
299