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 junit.framework.TestCase;
24 
25 import java.lang.annotation.Annotation;
26 import java.lang.annotation.Retention;
27 
28 /**
29  * @author crazybob@google.com (Bob Lee)
30  */
31 public class BindingAnnotationTest extends TestCase {
32 
testAnnotationWithValueMatchesKeyWithTypeOnly()33   public void testAnnotationWithValueMatchesKeyWithTypeOnly() throws CreationException {
34     Injector c = Guice.createInjector(new AbstractModule() {
35       @Override
36       protected void configure() {
37         bindConstant().annotatedWith(Blue.class).to("foo");
38         bind(BlueFoo.class);
39       }
40     });
41 
42     BlueFoo foo = c.getInstance(BlueFoo.class);
43 
44     assertEquals("foo", foo.s);
45   }
46 
testRequireExactAnnotationsDisablesFallback()47   public void testRequireExactAnnotationsDisablesFallback() {
48     try {
49       Guice.createInjector(new AbstractModule() {
50         @Override
51         protected void configure() {
52           binder().requireExactBindingAnnotations();
53           bindConstant().annotatedWith(Blue.class).to("foo");
54           bind(BlueFoo.class);
55         }
56       });
57       fail();
58     } catch (CreationException expected) {
59       assertContains(expected.getMessage(), "No implementation for java.lang.String annotated with",
60           "BindingAnnotationTest$Blue(value=5) was bound",
61           "at " + BindingAnnotationTest.class.getName(),
62           getDeclaringSourcePart(getClass()));
63     }
64   }
65 
testRequireExactAnnotationsDoesntBreakIfDefaultsExist()66   public void testRequireExactAnnotationsDoesntBreakIfDefaultsExist() {
67        Guice.createInjector(new AbstractModule() {
68         @Override
69         protected void configure() {
70           binder().requireExactBindingAnnotations();
71           bindConstant().annotatedWith(Red.class).to("foo");
72           bind(RedFoo.class);
73         }
74       }).getInstance(RedFoo.class);
75   }
76 
testRequireExactAnnotationsRequireAllOptionals()77   public void testRequireExactAnnotationsRequireAllOptionals() {
78     try {
79       Guice.createInjector(new AbstractModule() {
80         @Override
81         protected void configure() {
82           binder().requireExactBindingAnnotations();
83           bindConstant().annotatedWith(Color.class).to("foo");
84           bind(ColorFoo.class);
85         }
86       });
87       fail();
88     } catch (CreationException expected) {
89       assertContains(expected.getMessage(), "No implementation for java.lang.String annotated with",
90           "BindingAnnotationTest$Color",
91           "at " + BindingAnnotationTest.class.getName(),
92           getDeclaringSourcePart(getClass()));
93     }
94   }
95 
testAnnotationWithValueThatDoesntMatch()96   public void testAnnotationWithValueThatDoesntMatch() {
97     try {
98       Guice.createInjector(new AbstractModule() {
99         @Override
100         protected void configure() {
101           bindConstant().annotatedWith(createBlue(6)).to("six");
102           bind(String.class).toInstance("bar");
103           bind(BlueFoo.class);
104         }
105       });
106       fail();
107     } catch (CreationException expected) {
108       assertContains(expected.getMessage(), "No implementation for java.lang.String annotated with",
109           "BindingAnnotationTest$Blue(value=5) was bound",
110           "at " + BindingAnnotationTest.class.getName(),
111           getDeclaringSourcePart(getClass()));
112     }
113   }
114 
115   static class BlueFoo {
116     @Inject @Blue(5) String s;
117   }
118 
119   static class RedFoo {
120     @Inject @Red String s;
121   }
122 
123   static class ColorFoo {
124     @Inject @Color(b=2) String s;
125   }
126 
127   @Retention(RUNTIME)
128   @BindingAnnotation
129   @interface Blue {
value()130     int value();
131   }
132 
133   @Retention(RUNTIME)
134   @BindingAnnotation
135   @interface Red {
r()136     int r() default 42;
g()137     int g() default 42;
b()138     int b() default 42;
139   }
140 
141   @Retention(RUNTIME)
142   @BindingAnnotation
143   @interface Color {
r()144     int r() default 0;
g()145     int g() default 0;
b()146     int b();
147   }
148 
createBlue(final int value)149   public Blue createBlue(final int value) {
150     return new Blue() {
151       public int value() {
152         return value;
153       }
154 
155       public Class<? extends Annotation> annotationType() {
156         return Blue.class;
157       }
158 
159       @Override public boolean equals(Object o) {
160         return o instanceof Blue
161             && ((Blue) o).value() == value;
162       }
163 
164       @Override public int hashCode() {
165         return 127 * "value".hashCode() ^ value;
166       }
167     };
168   }
169 }
170