1 /* 2 * Copyright (C) 2012 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 18 package com.google.inject; 19 20 import junit.framework.TestCase; 21 22 /** 23 * Tests for {@link Binder#requireAtInjectOnConstructors()} 24 * 25 * @author sameb (at) google.com (Sam Berlin) 26 */ 27 public class RequireAtInjectOnConstructorsTest extends TestCase { 28 29 public void testNoCxtors_explicitBinding() { 30 try { 31 Guice.createInjector(new AbstractModule() { 32 @Override 33 protected void configure() { 34 bind(NoCxtors.class); 35 binder().requireAtInjectOnConstructors(); 36 } 37 }); 38 fail(); 39 } catch (CreationException ce) { 40 assertEquals(1, ce.getErrorMessages().size()); 41 Asserts.assertContains(ce.getMessage(), 42 "1) Explicit @Inject annotations are required on constructors, but " 43 + NoCxtors.class.getName() + " has no constructors annotated with @Inject", 44 "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); 45 } 46 } 47 48 public void testNoCxtors_jitBinding() { 49 Injector injector = Guice.createInjector(new AbstractModule() { 50 @Override 51 protected void configure() { 52 binder().requireAtInjectOnConstructors(); 53 } 54 }); 55 try { 56 injector.getInstance(NoCxtors.class); 57 fail(); 58 } catch (ConfigurationException ce) { 59 Asserts.assertContains(ce.getMessage(), 60 "1) Explicit @Inject annotations are required on constructors, but " 61 + NoCxtors.class.getName() + " has no constructors annotated with @Inject", 62 "while locating " + NoCxtors.class.getName()); 63 } 64 } 65 66 public void testNoCxtors_implicitBinding() { 67 try { 68 Guice.createInjector(new AbstractModule() { 69 @Override 70 protected void configure() { 71 bind(Interface.class).to(NoCxtors.class); 72 binder().requireAtInjectOnConstructors(); 73 } 74 }); 75 fail(); 76 } catch (CreationException ce) { 77 assertEquals(1, ce.getErrorMessages().size()); 78 Asserts.assertContains(ce.getMessage(), 79 "1) Explicit @Inject annotations are required on constructors, but " 80 + NoCxtors.class.getName() + " has no constructors annotated with @Inject", 81 "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); 82 } 83 } 84 85 public void testNoCxtors_inheritedByPrivateModules() { 86 try { 87 Guice.createInjector(new AbstractModule() { 88 @Override 89 protected void configure() { 90 binder().requireAtInjectOnConstructors(); 91 install(new PrivateModule() { 92 @Override 93 protected void configure() { 94 bind(NoCxtors.class); 95 } 96 }); 97 } 98 }); 99 fail(); 100 } catch (CreationException ce) { 101 assertEquals(1, ce.getErrorMessages().size()); 102 Asserts.assertContains(ce.getMessage(), 103 "1) Explicit @Inject annotations are required on constructors, but " 104 + NoCxtors.class.getName() + " has no constructors annotated with @Inject", 105 "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); 106 } 107 } 108 109 public void testNoCxtors_accumulatesAllErrors() { 110 try { 111 Guice.createInjector(new AbstractModule() { 112 @Override 113 protected void configure() { 114 bind(NoCxtors.class); 115 bind(AnotherNoCxtors.class); 116 binder().requireAtInjectOnConstructors(); 117 } 118 }); 119 fail(); 120 } catch (CreationException ce) { 121 assertEquals(2, ce.getErrorMessages().size()); 122 Asserts.assertContains(ce.getMessage(), 123 "1) Explicit @Inject annotations are required on constructors, but " 124 + NoCxtors.class.getName() + " has no constructors annotated with @Inject", 125 "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure", 126 "2) Explicit @Inject annotations are required on constructors, but " 127 + AnotherNoCxtors.class.getName() + " has no constructors annotated with @Inject", 128 "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); 129 } 130 } 131 132 public void testNoCxtors_separateOptionsForPrivateModules() { 133 try { 134 Guice.createInjector(new AbstractModule() { 135 @Override 136 protected void configure() { 137 bind(AnotherNoCxtors.class); 138 install(new PrivateModule() { 139 @Override 140 protected void configure() { 141 binder().requireAtInjectOnConstructors(); 142 bind(NoCxtors.class); 143 } 144 }); 145 } 146 }); 147 fail(); 148 } catch (CreationException ce) { 149 // This is testing that the parent module doesn't fail because it isn't included 150 // in the error message. 151 assertEquals(1, ce.getErrorMessages().size()); 152 Asserts.assertContains(ce.getMessage(), 153 "1) Explicit @Inject annotations are required on constructors, but " 154 + NoCxtors.class.getName() + " has no constructors annotated with @Inject", 155 "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); 156 } 157 } 158 159 public void testManyConstructorsButNoneWithAtInject() { 160 try { 161 Guice.createInjector(new AbstractModule() { 162 @Override 163 protected void configure() { 164 bind(ManyConstructors.class); 165 binder().requireAtInjectOnConstructors(); 166 } 167 }); 168 fail(); 169 } catch (CreationException ce) { 170 assertEquals(1, ce.getErrorMessages().size()); 171 Asserts.assertContains(ce.getMessage(), 172 "1) Explicit @Inject annotations are required on constructors, but " 173 + ManyConstructors.class.getName() + " has no constructors annotated with @Inject", 174 "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure"); 175 } 176 } 177 178 public void testRequireAtInjectStillAllowsToConstructorBindings() { 179 Injector injector = Guice.createInjector(new AbstractModule() { 180 @Override 181 protected void configure() { 182 try { 183 bind(ManyConstructors.class) 184 .toConstructor(ManyConstructors.class.getDeclaredConstructor()); 185 } catch (Exception e) { 186 throw new RuntimeException(e); 187 } 188 binder().requireAtInjectOnConstructors(); 189 } 190 }); 191 injector.getInstance(ManyConstructors.class); 192 } 193 194 private static interface Interface {} 195 private static class NoCxtors implements Interface {} 196 private static class AnotherNoCxtors {} 197 private static class ManyConstructors { 198 @SuppressWarnings("unused") ManyConstructors() {} 199 @SuppressWarnings("unused") ManyConstructors(String a) {} 200 @SuppressWarnings("unused") ManyConstructors(int a) {} 201 } 202 } 203