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 (at) google.com (Bob Lee) 30 */ 31 public class BindingAnnotationTest extends TestCase { 32 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 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 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 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 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 { 130 int value(); 131 } 132 133 @Retention(RUNTIME) 134 @BindingAnnotation 135 @interface Red { 136 int r() default 42; 137 int g() default 42; 138 int b() default 42; 139 } 140 141 @Retention(RUNTIME) 142 @BindingAnnotation 143 @interface Color { 144 int r() default 0; 145 int g() default 0; 146 int b(); 147 } 148 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